아래 그림처럼 ViewPager 형태인데 다음 페이지가 살짝 보이는 UI를 만드는 경우가 종종 있다. 이번 포스트에서는 ViewPager2를 이용해 이 화면을 만드는 방법을 다뤄보려고 한다.

 

val currentVisibleItemPx = DimensionUtils.dp2px(requireContext(), 40f).toInt()

margin_pager.addItemDecoration(object: RecyclerView.ItemDecoration() {
    override fun getItemOffsets(outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State) {
        outRect.right = currentVisibleItemPx
        outRect.left = currentVisibleItemPx
    }
})

ViewPager에서 inflate 된 페이지는 부모의 width를 따라가게 되므로 우선 각 페이지가 전체 영역을 잡지 않게 여백을 만들어둔다. 현재 보여진 위치로부터 양 옆에 margin을 추가한다. 그러면 아래 그림과 같은 상태가 된다.

 

 

val nextVisibleItemPx = DimensionUtils.dp2px(requireContext(), 20f).toInt()
val pageTranslationX = nextVisibleItemPx + currentVisibleItemPx

margin_pager.offscreenPageLimit = 1

margin_pager.setPageTransformer { page, position ->
    page.translationX = -pageTranslationX * ( position)
}

 

다음은 이전 페이지와 다음 페이지에 이동 효과를 줘야한다. 먼저 첫번째는 offscreenPageLimit 값을 설정는데 이 속성은 ViewPager2가 스크린에 현재 페이지로부터 얼만큼 떨어져 있는 페이지를 미리 생성 할 것인지 설정하는 함수다. offscreenPageLimit 값이 1이고, 5번 페이지가 현재 위치라면 ViewPager2는 4, 6번 페이지도 미리 생성 해둔다.

 

그 다음은 setPageTransformer 함수를 사용하는 것이다. 이 콜백은 현재 포커싱된 page 뷰 객체를 받을 수 있고 각 page 별로 포커싱 된 페이지로부터 얼마만큼 떨어져 있는지 비율 정보를 position으로 받을 수 있다. 아래 그림에선 현재 페이지가 1번에 포커싱돼 있어서 이전 페이지인 0번 페이지는 -1f만큼 떨어져 있게 되고, 다음 페이지인 2번 페이지는 1f만큼 떨어져 있게 된다. 

 

 

이 정보 값을 이용하면 0번과 2번 페이지를 필요한 만큼 이동시킬 수 있다. translationX 값을 변경하면 0번과 2번 페이지가 움직여서 미리보기 형태로 볼 수 있게 된다.

 

728x90