본문 바로가기

이상/Andrioid

[Android/Kotlin] ViewPager 사용하기

반응형

Android에서 SwipeView 기능을 하는 것으로 ViewPager가 있다.

 

화면을 Swipe하여 슬라이드 효과를 주면서 화면을 전환할 수 있다.

 

2019년 구글에서 ViewPager2를 내놓았으며 당연하게도 기존 ViewPager보다는 ViewPager2를 권장하고 있다.

 

AndroidX로 넘어가면서 뭔가 많은 변화가 있었는데 그런 이유들 때문인 것 같다.

 

(로 newInstance()를 이용해서 Fragment를 생성하면

빈 생성자를 만들어 bundle을 이용하여 데이터를 전달하는 방식으로 데이터를 유지했는데

FragmentFactory가 생겨나면서 Kotlin에서는 아예

class SomeFragment(private val str: String) : Fragment() {

}

이런식으로 Fragment를 생성할 수도 있게 되었다. 잡소리가 길다.)

 

Docs에서 공식적으로 기존 ViewPager보다는 ViewPager2를 권장

 

 

ViewPager를 구현하기 위해서는

 

ViewPager가 배치될 화면, PagerAdapter, Paging 될 화면 최소 2개

 

가 필요하다.

 

 

 

1. MainActivity

 

MainActivity는 ViewPagerFragment를 띄워주는 역할만 할 것이므로

 

LinearLayout을 전체화면으로 지정해주고

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">
 
    <LinearLayout
        android:id="@+id/fragmentFrame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent">
    </LinearLayout>
 
</androidx.constraintlayout.widget.ConstraintLayout>
cs

 

MainActivity LinearLayout

 

해당 Layout에 ViewPagerFragment를 띄워준다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
 
        // ViewPagerFragment를 fragmentFrame에 띄우기
        val transaction = supportFragmentManager.beginTransaction()
        transaction.add(
                    R.id.fragmentFrame,
                    ViewPagerFragment()
                )
                .commit()
    }
}
 
cs

 

 

 

2. ViewPagerFragment

 

ViewPagerFragment를 만들고 .xml에 ViewPager를 추가해준다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ViewPagerFragment">
 
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/black"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">
    </androidx.viewpager.widget.ViewPager>
 
</androidx.constraintlayout.widget.ConstraintLayout>
cs

 

ViewPagerFragment ViewPager

 

 

 

3. Paging될 화면 2개 생성

 

화면을 Swipe해야하므로 최소 2개의 화면이 필요하다.

 

ViewPager의 기능에 목적이 있기 때문에 특별한 기능없이

 

배경색을 변경해주고 TextView만 추가해주었다.

 

FirstFragment
SecondFragment

 

 

 

4. PagerAdapter

 

ViewPager의 PagerAdapter는 FragmentStatePagerAdapter를 상속받아 구현한다.

 

참고로 FragmentStatePagerAdapter는 완전히 deprecated 되었다.

FragmentStatePagerAdapter is deprecated

 

 

PagerAdapter에 Fragment를 담고 있는 ArrayList타입의 변수를 만들어

 

ViewPager에서 사용될 화면들을 담는다.

 

그리고 해당 변수를 이용하여 getItem(), getCount()에 적절하게 넘겨준다.

 

1
2
3
4
5
6
7
8
9
10
11
12
class ViewPagerAdapter(fm : FragmentManager) : FragmentStatePagerAdapter(fm){
 
    private var fragments : ArrayList<Fragment> = ArrayList()
 
    override fun getItem(position: Int): Fragment = fragments[position]
 
    override fun getCount(): Int = fragments.size
 
    fun addItems(fragment : Fragment){
        fragments.add(fragment)
    }
}
 
cs

 

PagetAdapter에서 할 일은 여기까지이다.

 

실행해보면 아래와 같이 작동한다.

 

 

ViewPager

 

ViewPager는 현재 페이지를 기준으로 양 옆, 총 3개의 페이지만 관리하고

 

나머지 페이지는 메모리에서 삭제한다.

 

ViewPager의 페이지 관리

 

 

 

5. PagerTabStrip

 

ViewPager를 더욱 완벽하게 만들어 줄 친구이다.

 

이름 그대로 ViewPager를 탭 형식으로 사용할 수 있게 해주며 가늘게 생겼다.

 

Docs의 PagerTabStrip

 

Docs에서 살펴보면 ViewPager의 현재, 다음, 이전 페이지에 대한 대화형 표시기라고 되어있다.

 

ViewPager와 PagerTabStrip을 함께 사용하면 왠만한 수평형 Swipe 탭 화면은 문제 없을 것 같다.

 

그리고 PagerTitleStrip의 하위클래스라고 한다.

 

PagerTitleStrip은 PagerTabStrip과 똑같이 생겼지만

(PagerTitleStrip은 Title에 밑줄이 없고 PagerTabStrip은 밑줄이 있는 디테일한 차이를 제외하고)

 

ViewPager를 Swipe할 때 현재 페이지를 보여주기만 할 뿐 클릭 기능은 없다.

 

 

ViewPagerFragment에 추가해주었던 ViewPager 안에

 

PagerTabStrip을 추가해주고 layout_gravity 속성을 top으로 지정해준다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".ViewPagerFragment">
 
    <androidx.viewpager.widget.ViewPager
        android:id="@+id/viewPager"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:background="@color/black"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent">
        <androidx.viewpager.widget.PagerTabStrip
            android:id="@+id/pager_tab_strip"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_gravity="top"
            android:textColor="#000000"
            android:background="@color/white"
            android:paddingBottom="4dp"
            android:paddingTop="4dp"/>
    </androidx.viewpager.widget.ViewPager>
 
</androidx.constraintlayout.widget.ConstraintLayout>
cs

 

ViewPager PagerTabStrip 추가

 

ViewPager with PagerTabStrip

 

 

ViewPager는 간단한 Swipe 화면을 만드는데에 강력한 것 같다.

 

 

하지만 구글에서 ViewPager2을 따로 만든 이유가 있을 것이고

 

FragmentStatePagerAdapter는 아예 deprecated 되었으니 ViewPager는 사용하지 않는게 맞는 것 같다.

 

 

기존의 화면 회전 시 발생하는 문제를 대처할 방안들이

 

AndroidX가 생기면서 함께 여러가지가 나왔는데

 

ViewPager2도 그러한 방안의 역할을 하지 않을까 싶다.

 

 

다음에는 ViewPager2 아니면 FragmentFactory 아니면 GridView에 대해 다룰 예정이다.

 

끝.

 

 

 

참고.

https://recipes4dev.tistory.com/148

 

반응형