[Android/Kotlin/Tip] ViewPager2 Circular Scroll - 끝에서 처음으로 이동

Notepad96

·

2022. 8. 19. 23:37

300x250

 

 

1. 설명

 

결과

 

이번 글에서는 ViewPager를 사용할 때 처음에서 끝으로, 끝에서 처음으로 순환하는 구조를 갖도록 하는 방법에 대하여 기술한다.

 

 

기존 ViewPager는 아래 그림처럼 구성되어 있어 A 페이지서 B 페이지로 B 페이지서 C 페이지로 양방향 이동이 가능하였다.

 

하지만 이와 같은 구조에서는 A 페이지와 C 페이지 간 양방향 이동이 불가하다는 제약 사항이 발생한다.

기존 Viewpager

 

 

따라서 이를 해결하기 위해서는 아래와 같은 구조로 변경해주면 각 페이지들을 순환하는 구조로 만들어 줄 수 있다.

 

그래서 이를 Circular Scroll이나 Infinite Scroll라고 명칭 하는 것 같다.

 

순환 ViewPager

 

 

 

이번 글에서는 Circular Scrolling 기능을 구현하기 위한 내용으로서 기본적으로 Tab Layout과 ViewPager2를 이용하여 각 페이지를 구성하는 방법은 아래의 이전에 작성한 글이 있으니 이를 참고하면 될 것 같다.

 

 

[Android/Kotlin] TabLayout + ViewPager2 - Slide하여 화면 전환

1. 요약 이번 글에서는 TabLayout과 ViewPager2를 사용하여서 Tab 할 수 있는 메뉴가 있으며 이를 클릭하면 화면이 전환되며, 마찬가지로 좌우로 Slide 하였을 시 화면이 전환되도록 구성하는 방법에 관

notepad96.tistory.com

 


 

1. Circular Scrolling 기능을 구현하기 위해서는 우선 ViewPager의 registerOnPageChangeCallback으로 콜백 리스너를 구현해준다.

 

 

2. 그러면 오버라이드 할 수 있는 함수가 3가지 onPageScrolled, onPageSelected, onPageScrollStateChanged 가 있으며, 이들을 다 오버라이드 해주며 각 역할은 함수명을 보면 대충 어느 역할을 하는지 유추 가능하므로 자세한 설명은 생략하겠다.

 

# MainActivity.kt

...

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    
    ...

    binding.viewPager01.registerOnPageChangeCallback(object: ViewPager2.OnPageChangeCallback() {
        var currentState = 0
        var currentPos = 0

        override fun onPageScrolled(
            position: Int,
            positionOffset: Float,
            positionOffsetPixels: Int
        ) {
            if(currentState == ViewPager2.SCROLL_STATE_DRAGGING && currentPos == position) {
                if(currentPos == 0) binding.viewPager01.currentItem = 2
                else if(currentPos == 2) binding.viewPager01.currentItem = 0
            }
            super.onPageScrolled(position, positionOffset, positionOffsetPixels)
        }

        override fun onPageSelected(position: Int) {
            currentPos = position
            super.onPageSelected(position)
        }

        override fun onPageScrollStateChanged(state: Int) {
            currentState = state
            super.onPageScrollStateChanged(state)
        }
    })
}

 

3. 그다음 현재의 상태와 위치 값을 저장할 2개의 변수 currentStatecurrentPos를 생성한다.

 

 

4. 그리고 오버라이드 하였던 onPageSelected, onPageScrollStateChanged 함수에 페이지가 변하였을 경우 현재 페이지의 Position 값과 State를 변수에 저장할 수 있도록 코드를 작성한다.

 

 

5. onPageScrolled는 페이지가 스크롤할 때 호출되며, 재정의한 내용을 보면 우선 

 

5-1. 첫 번째 IF문에서 현재 상태가 ViewPager2.SCROLL_STATE_DRAGGING이며 현재 위치와 Position 값이 일치할 경우를 판별한다.

 

여기서 SCROLL_STATE_DRAGGING은 fake drag 되고 있음을 가리킨다. 이를 설명하기 위해서 예를 들자면 원래 첫 번째 페이지인 A에서 왼쪽으로 페이지를 넘기려고 drag를 할 경우 drag는 하였지만 페이지는 이동되지 않는다.

 

이때 상태가 fake drag로서 이 SCROLL_STATE_DARGGING 상태가 발생한다는 것은 즉 시작과 끝 페이지에서 이동 불가능한 방향으로 drag 하였음을 나타낸다.

 

 

상태 값에 대한 자세한 설명은 아래 공식 문서에서 확인할 수 있다.

 

5-2. 마지막으로 currentPos 현재 위치가 0이면 첫 번째 페이지의 위치 중이며 마지막 페이지로 이동하고자 하는 것이기 때문에, 마지막 페이지의 Position값인 2를 반대로 2일 경우 0으로 이동하도록 만들어주면 순환하는 ViewPager가 만들어진다.

 

 

 

 

2. 전체 파일

 

 

GitHub - Notepad96/BlogExample02

Contribute to Notepad96/BlogExample02 development by creating an account on GitHub.

github.com

 

 

 

 

300x250