뷰페이저를 사용하며 스크롤 되는 모션을 바꿔보고 싶은 욕심이 생겼다.
기존의 뷰페이저는 단순히 이미지가 이동하며 스크롤 되는 애니메이션을 가지고 있었는데, 이 애니메이션을 영상효과의 디졸브 처럼 전환하고 싶었다.
이리저리 알아보다가 해당 애니메이션이 Cross Fade
라는 키워드로 불린다는걸 알았고, 해당 키워드로 조금 더 검색해보다가 Page Transformer
에 대해 알게됐다.
ViewPager2
에서 기본 화면 전환 애니메이션과 다른 애니메이션을 사용하고 싶을 경우 Page Transformer
인터페이스를 사용해 원하는 애니메이션을 구현해 ViewPager2
객체에 전달할 수 있다.
// setPagerTransformer메서드로 커스텀한 Page Transformer를 전달
binding.vpTopContentImage.setPageTransformer(CrossFadePageTransformer)
Page Transformer
인터페이스는 단일 메서드인 transformPage
를 가지고 있는데 이 메서드를 통해 프래그먼트간 전환시 원하는 동작을 구현한다.
transformPage
메서드는 ViewPager
가 스크롤 되며 전환될때 현재 페이지와 인접한 전/후의 페이지에 대해서 각각 호출된다.
즉, 스크롤을 할 경우 이전 | 현재 | 다음
과 같이 총 3번의 메서드가 호출된다.
object CrossFadePageTransformer : PageTransformer {
override fun transformPage(page: View, position: Float) { ... }
}
transformPage
메서드로 전달받는 position
은 각 페이지의 현재 위치를 나타낸다. 페이지가 가운데 있을 경우 position
값은 0
이며, 왼쪽끝에서는 -1
, 오른쪽 끝에서는 1
로 전달된다.
따라서 스크롤시 trnasformPage
메서드는 이전 View의 position
이 -1
, 현재 화면의 View는 0
, 다음의 View는 1
로 호출된다.
이를 활용해서 페이지가 스크롤될때 다양한 효과를 구현할 수 있다.
Cross Fade
효과 적용을 위해 스크롤되어도 아이템이 화면을 벗어나지 않도록 position
에 따라 translateX
를 조정하도록 했다.
동시에 서로 사라짐과 동시에 나타나게 할 수 있도록 alpha
값도 함께 조정했다.
object CrossFadePageTransformer : PageTransformer {
override fun transformPage(page: View, position: Float) {
page.apply {
// 뷰가 화면 밖에있을경우 alpha값을 0으로 조정
if (position < -1f || position > 1f) {
alpha = 0f
return
}
// 뷰의 width값에서 움직인 position값을 빼서 화면에 뷰가 고정되어있게 만듬
translationX = page.width * -position
alpha = Math.max(0f, 1f - Math.abs(position))
translationX = -page.width * position
page.alpha = alpha
}
}
}
Cross Fade
효과 말고도 다양한 효과를 적용해 볼 수 있다.
심화 과정이 끝났다...
이제 실전프로젝트만 남았다...
짤 맘에 드네요