[Android] 리사이클러뷰 스크롤 시 뷰페이저 비활성화

KIMGEUNTAE·2023년 5월 22일
2

Android

목록 보기
3/8

뷰페이저 비 활성화

뷰페이저 안에 특정 리사이클러뷰가 있는 부분에 다른 탭으로 넘어가지 않도록 뷰페이저의 움직임의 비활성화가 필요했습니다.

해당 샘플 코드는 메인액티비티 안에서 리사이클러뷰를 프래그먼트에 한거지만해서 한거지만

프래그먼트안에 프래그먼트는 Include로 표현 한 것은

ViewPager가 터치되면 해당 터치 이벤트의 x, y 좌표를 가져와서 이 좌표가 특정 RecyclerView의 영역 내에 있는지 확인하고 뷰페이저 기능을 비활성하고 터치가 끝나면 스와이프 기능을 다시 활성화 하는 걸로 해서 깃허브에 주석으로 처리해서 넣었지만

샘플에는 액티비티에 뷰페이저는 인터페이스를 설정하고 onScroll 메서드를 호출하는지 결정하고 리사이클러뷰가 스크롤 되는 동안 뷰페이저의 스와이프를 비활성화 합니다.


ViewPager

MainActivity.kt

class MainActivity : AppCompatActivity(), OnRecyclerViewScrollListener {

    private lateinit var binding: ActivityMainBinding
    private var viewPagerFragment: ViewPagerFragment? = null

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.viewPager.adapter = ViewPagerAdapter(supportFragmentManager)
        binding.tabLayout.setupWithViewPager(binding.viewPager)

        binding.tabLayout.getTabAt(0)?.text = "뷰페이저"
        binding.tabLayout.getTabAt(1)?.text = "프래그먼트"

    }

    override fun onScroll(isScrolling: Boolean) {
        binding.viewPager.isSwipeEnabled = !isScrolling
    }

    fun disableSwipe() {
        binding.viewPager.isSwipeEnabled = false
    }

    fun enableSwipe() {
        binding.viewPager.isSwipeEnabled = true
    }


}
  • onScroll
    인터페이스의 콜백 메서드로, 리사이클러뷰가 스크롤될 때 호출되며, 리사이클러뷰가 스크롤되고 있으면 뷰페이저의 스와이프를 비활성화하고, 스크롤되고 있지 않으면 뷰페이저의 스와이프를 활성화 함

  • disableSwipe , enableSwipe
    이 두 메서드는 뷰페이저의 스와이프를 비활성화하거나 활성화하는 기능이며
    메서드들은 리사이클러뷰가 스크롤될 때 뷰페이저의 스와이프를 제어하는 데 사용


RecyclerView

ViewPagerFragment.kt

  class ViewPagerFragment : BaseFragment<FragmentViewpagerBinding>(R.layout.fragment_viewpager) {

  private var scrollListener: OnRecyclerViewScrollListener? = null

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
      super.onViewCreated(view, savedInstanceState)

      val top: Array<Int> = arrayOf(
          R.drawable.first,
          R.drawable.second,
          R.drawable.qwe
      )

      val bottom: Array<Int> = arrayOf(
          R.drawable.ujm,
          R.drawable.fifth,
          R.drawable.asd
      )

      // 상단
      val topAdapter = TopAdapter(top)
      binding.TopRecyclerViewId.adapter = topAdapter
      binding.TopRecyclerViewId.layoutManager =
          LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)

      // 하단
      val bottomAdapter = BottomAdapter(bottom)
      binding.BottomRecyclerViewId.adapter = bottomAdapter
      binding.BottomRecyclerViewId.layoutManager =
          LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)

      binding.TopRecyclerViewId.addOnScrollListener(object : RecyclerView.OnScrollListener() {
          override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) {
              super.onScrollStateChanged(recyclerView, newState)
              // RecyclerView가 스크롤 중일 때 ViewPager의 스와이프를 비활성
              if (newState != RecyclerView.SCROLL_STATE_IDLE) {
                  (activity as? MainActivity)?.disableSwipe()
              } else {
                  // RecyclerView가 스크롤되지 않는 경우 ViewPager의 스와이프를 활성화
                  (activity as? MainActivity)?.enableSwipe()
              }
          }
      })

  }

  override fun onAttach(context: Context) {
      super.onAttach(context)
      if (context is OnRecyclerViewScrollListener) {
          scrollListener = context
      }
  }

  override fun onDetach() {
      super.onDetach()
      scrollListener = null
  }

}
  • scrollListener
    리사이클러뷰가 스크롤될 때 호출되는 콜백 메서드를 정의하며
  • addOnScrollListener
    메서드 내에서 RecyclerView가 스크롤 중일 때 ViewPager의 스와이프를 비활성해서 스와이프를 방지하고 RecyclerView를 스크롤 되지 않으면 뷰페이저의 스와이프가 다시 활성화 합니다.

  • onAttach
    프래그먼트가 액티비티에 연결될 때 호출되는 콜백 메서드이며 여기서 액티비티가 OnRecyclerViewScrollListener 인터페이스를 구현하고 있다면, scrollListener 변수에 액티비티의 참조를 저장

  • onDetach
    프래그먼트가 액티비티에서 분리될 때 호출되는 콜백 메서드이며 여기서 scrollListener 변수를 null로 설정하여 참조를 제거

Adapter

ViewPager.Adapter

class ViewPagerAdapter(fragmentManager: FragmentManager) : FragmentPagerAdapter(fragmentManager, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {

  private val fragments = listOf(
      ViewPagerFragment(),
      SecondFragment()
  )

  override fun getItem(position: Int): Fragment {
      return fragments[position]
  }

  override fun getCount(): Int {
      return fragments.size
  }
}
  • 프래그먼트 어댑터로 뷰페이저를 설정

알아보니 뷰페이저2는 비활성화하는 것이 좀 더 간단한 것 같았지만 구현되어 있는 것은 뷰페이저 안에서 멈춰야 했고 뷰페이저2로 바꿔서 하는 것이 손이 더 많이 가서 뷰페이저 안에서 멈추는 게 낫겠다고 생각을 하게 되었다.


깃허브 : https://github.com/GEUN-TAE-KIM/DisableRecycerView_ViewPager_Sample.git


profile
Study Note

0개의 댓글