안드로이드 Circular ViewPager 사용하기

Ddudduu·2021년 11월 15일
0

지난 프로젝트에서 ViewPager 로 메뉴들을 보여주는데, 순환하게끔 구현해달라는 요청이 있었다.
열심히 구글링해보니 Circular ViewPager 라고 하는듯!

기본적인 viewPager 는 구현했다는 가정 하에 글을 작성해보려한다 🥳

stackoverflow 를 참고했다!

1. 변수 선언

 private var currentPosition: Int = 0
 private var scrollState: Int = 0
  • 현재 위치를 저장하는 currentPosition, scroll 상태를 저장하는 scrollState 두 개의 변수를 선언한다.

2. ViewPager2.OnPageChangeCallback 구현하기

  • 선택된 페이지의 상태가 변경됐을 때 처리하는 콜백리스너이다.
    오버라이드할 수 있는 함수가 세가지 있음!

2-1. onPageScrollStateChanged()

 private val pageChangeCallback = object : ViewPager2.OnPageChangeCallback() {
    override fun onPageScrollStateChanged(state: Int) {
      super.onPageScrollStateChanged(state)
      handleScrollState(state)
      scrollState = state
    }

    private fun handleScrollState(state: Int) {
      if (state == ViewPager2.SCROLL_STATE_IDLE && scrollState == ViewPager2.SCROLL_STATE_DRAGGING) {
        setNextItemIfNeeded()
      }
    }

    private fun setNextItemIfNeeded() {
      // settle 이 아니라면 다음 화면 넘어가기
      if (!isScrollStateSettling()) {
        handleSetNextItem()
      }
    }

    private fun isScrollStateSettling(): Boolean {
      return scrollState == ViewPager2.SCROLL_STATE_SETTLING
    }

    private fun handleSetNextItem() {
      val lastPosition = binding.viewPager.adapter?.itemCount?.minus(1)

      // 첫번째 화면이면 마지막 화면으로
      if (currentPosition == 0) {
        if (lastPosition != null) {
          binding.viewPager.setCurrentItem(lastPosition, false)
        }
        // 마지막 화면이면 첫번째 화면으로
      } else if (currentPosition == lastPosition) {
        binding.viewPager.setCurrentItem(0, false)
      }
    }
  • 우선, scroll state 가 변경될 때 호출되는 onPageScrollStateChanged() 이다.
  • 전체적인 flow
    scroll state 가 ViewPager2.SCROLL_STATE_SETTLING (스크롤이 끝까지 간 상태) 가 아니라면,
    1️⃣ 현재 첫번째 화면이면 ▶️ 마지막 화면으로 이동
    2️⃣ 마지막 화면이면 ▶️ 첫번째 화면으로 이동
  • 이게 무슨 말인가.. 하고 보니
    보통 스크롤하면
    SCROLL_STATE_DRAGGING ▶️ SCROLL_STATE_SETTLING ▶️ SCROLL_STATE_IDLE 순서로 호출된다.
  • 반면 첫번째 화면 ▶️ 마지막 화면 or 마지막화면 ▶️ 첫번째 화면 으로 스크롤하면 스크롤 상태가
    SCROLLSTATE_DRAGGING ▶️ SCROLL_STATE_IDLE 로 변경된다.

  • 그러면! handleScrollState() 호출 후, scrollState 가 업데이트되니까 state 가 IDLE 이면 scrollState 는 DRAGGING 이 된다.
  • state == SCROLL_STATE_IDLE && scrollState == SCROLL_STATE_DRAGGING
    🔼 이 상태의 의미는 순환할 때의 상태라는 것!


2-2. onPageScrolled()

  • onPageScrolled() 의 메소드 중 하나이지만 여기에서 오버라이드할 내용은 없음!


2-3. onPageSelected()

override fun onPageSelected(position: Int) {
      super.onPageSelected(position)
      currentPosition = position
    }
  • 새로운 페이지로 넘어갔을때 호출되는 onPageSelected() 에서는 currentPosition 을 업데이트 해준다.


결과는 이렇다.

벗... 순환할때 끊기는 문제가 발생하는데 이건 또 해결해봐야겠다...

profile
Android

0개의 댓글