[Android] ViewPager2

Twaun·2022년 7월 17일
0

Android

목록 보기
11/24

ViewPager 가 뭘까?

한 화면에서 여러 뷰를 스와핑해서 전환하는 기능이 필요할 때 사용한다. 여기서 페이지란 여러 뷰가 될 수도 있고 프래그먼트가 될 수 도 있다.

💡 잠깐!!
RecyclerView도 이런 데이터를 리스트로 표현하는 것인데 뭐가 다른거지?

ViewPager 와 RecyclerView 는 데이터를 리스트로 표현하고 이들을 스와핑할 수 있다는 점에서 비슷한 기능을 가지고 있다.
하지만 ViewPager는 한번에 하나의 데이터만 보여줄 수 있는(미리보기 기능이 존재하긴 하는데 우선 완벽히 공존을 안된다) 반면 RecyclerViewsms 한번에 보여줄 수 있는 데이터 수에는 제한이 없다.

즉, ViewPager는 여러 데이터를 하나씩 애니메이션을 주면서 스와핑 하는데 특화되어 있다.

ViewPager 와 ViewPager2의 차이


ViewpagerViewPager2
좌우 스크롤좌우 상하 스크롤
FragmentStatePagerAdapterFragmentStateAdapter
PagerAdapterRecyclerView.Adapter
addPageChangeListener()registerOnpageCallback()

이 외에도 여러 리스너가 변경되고 추가되었고 애니메이션이 좀더 향상 되었다.

사용 준비

간단히 화면 두 개를 좌우로 스와핑하는 화면을 만들어보자!!

(gif)

필요한 것

  • 이동 될 화면 Fragment 2개
  • Activity
  • ViewPager2
  • Adapter
  • Radio Group, Radio Button

사용

XML

<androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <androidx.viewpager2.widget.ViewPager2
            android:id="@+id/viewPager"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:background="@color/mono4"
            app:layout_constraintBottom_toTopOf="@+id/rg_navigation"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            app:layout_constraintVertical_weight="10" />

        <RadioGroup
            android:id="@+id/rg_navigation"
            android:layout_width="0dp"
            android:layout_height="0dp"
            android:orientation="horizontal"
            app:layout_constraintBottom_toBottomOf="parent"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintHorizontal_bias="0.5"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toBottomOf="@+id/viewPager"
            app:layout_constraintVertical_weight="1" >

            <RadioButton
                android:id="@+id/rb_a"
                android:layout_weight="1"
                android:layout_width="0dp"
                android:background="@drawable/radiobutton"
                android:button="@null"
                android:text="A"
                android:gravity="center"
                android:textColor="@color/mono8"
                android:fontFamily="@font/semi_bold"
                android:layout_height="match_parent"/>

            <RadioButton
                android:id="@+id/rb_b"
                android:layout_weight="1"
                android:layout_width="0dp"
                android:text="B"
                android:gravity="center"
                android:textColor="@color/mono8"
                android:fontFamily="@font/semi_bold"
                android:background="@drawable/radiobutton"
                android:button="@null"
                android:layout_height="match_parent"/>

        </RadioGroup>

    </androidx.constraintlayout.widget.ConstraintLayout>

Adapter

class TestViewPageAdapter(fragment: FragmentActivity) : FragmentStateAdapter(fragment) {

    private val pageList = mutableListOf<Fragment>()

    override fun getItemCount(): Int {
        return pageList.size
    }

    override fun createFragment(position: Int): Fragment {
        return pageList[position]
    }

    fun addFragment(newFragment: Fragment) { pageList.add(newFragment) }
}

Viewpager

ViewPager 관련 data class

data class Navigation(
    val name: String,
    val newInstance: (()-> Fragment),
    val radioButtonId: Int
)

val naviList = mutableListOf<Navigation>()
naviList.add(Navigation("A", { AFragment.newInstance() }, R.id.rb_a))
naviList.add(Navigation("B", { BFragment.newInstance() }, R.id.rb_b))

페이지(Fragment) 추가

binding.viewPager.apply {
	adapter = TestViewPageAdapter(this@TestActivity).apply {
		naviList.forEach{ addFragment(it.newInstance()) }
	}
}

RadioGroup 설정

binding.rgNavigation.apply {
	// init check
	check(naviList.first().radioButtonId)
    setOnCheckedChangeListener { _, id ->
    	// 클릭된 index 찾기
    	val index = naviList.indices.find {
        	naviList[it].radioButtonId == id 
		} ?: 0
        // 이동할 fragment로 page 이동
        // smoothScroll이 true 면 정말 스무시하게 페이지 전환이 된고 false 면 애니메이션 없이 띡띡 페이지 이동한다. 
		binding.viewPager.setCurrentItem(index, true)
	}
}

고찰

Radio Group 으로 Bottom Navigation 느낌을 나도록 그려보았다.
Bottom Navigation View 를 사용해도 되지만 좀 더 완벽히 커스텀? 하기 위해 ? RadioButton 으로 구성된 Radio Group으로 구현해봤다. 원하는 뷰를 다 그릴 수 있을 것 같다.

하지만 라디오 개수에 따라 뷰를 다시 그리고 지워야할 번거로움이 있으므로 커스텀뷰를 만들어 개수, border, buttonStyle, checkListener 등 으로 조작이 가능하면 좋겠다는 생각이 있다. 근데 우선 이 글은ViewPager2를 위한 글이니 여기까지 한다.

이 ViewPager를 통해서 광고를 보여주는 듯 하고 미리보기? 기능도 존재하고 애니메이션도 세부 설정이 가능해보인다. 이 추가 기능들은 새 글을 만들어서 작성해볼 예정이다.

profile
Android Developer

0개의 댓글