본문 바로가기
Android App/Kotlin

컨테이너:화면전환-뷰페이저(ViewPager), 탭레이아웃(TabLayout) / 뷰 사용

by AppJinny 2022. 11. 16.

*컨테이너:화면전환-뷰페이저(ViewPager), 탭레이아웃(TabLayout) / 뷰 사용

-뷰를 사용하여 뷰페이저 구현

-하나의 아이템 레이아웃에서 반복적으로 동일한 구조의 텍스트나 이미지를 보여주는 용도일 때 사용

-목록을 가로로 스와이프해서 보여줄 필요가 있을 때 사용(ex. 사진 갤러리의 동작방식)

 

*뷰페이저(ViewPager)

-한 화면에 하나의 아이템만 보이는 컨테이너

-한 화면에 여러 아이템을 보여주는 리사이클러뷰와 구현방식이 비슷함

-레이아웃에서 <ViewPager2 /> 로 사용

-어댑터를 만들어 페이저 어댑터를 상속받아 뷰페이저에 보일 화면들 연결

--FragmentStateAdapter : 프래그먼트를 담을 수 있는 페이저 어댑터

--RecyclerView.Adapter : 뷰를 사용해 뷰페이저를 만들 때 사용하는 어댑터(리사이클러뷰랑 구현이 같음)

-탭 레이아웃과 연결 시 TabLayoutMadiator() 사용

 

*탭 레이아웃(TabLayout)

-화면에 탭 메뉴를 만들어 메뉴 클릭 시 해당 페이지로 이동하는 컨테이너

-레이아웃에서 <com.google.android.material.tabs.TabLayout /> 로 사용

-뷰페이저와 연결 시 TabLayoutMadiator() 사용

 

*뷰를 사용하는 뷰페이저 만들기

-동일한 구조로 되어있는 뷰 4개 보여주기

-하나의 뷰에서 사용하는 하나의 아이템 레이아웃 사용

 

-build.gradle

-- android{} 에 뷰바인딩 추가

//뷰바인딩
buildFeatures{
    viewBinding true
}

 

-MainActivity.kt

class MainActivity : AppCompatActivity() {

    //뷰바인딩
    val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }

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

        //1
        //뷰를 사용하는 뷰페이저 만들기
        //뷰를 사용하여 뷰페이저 구현 : 하나의 아이템 레이아웃 사용, 반복적으로 동일한 구조의 뷰를 보여줄 때 사용
        //목록을 가로로 스와이프해서 보여줄 필요가 있을 때 사용(ex. 사진갤러리 앱 동작방식)
        //프래그먼트를 사용하여 뷰페이저 구현 : 각 화면들이 독립적으로 구성될 때 사용

        //1-1
        //하나의 뷰에서 사용할 아이템 레이아웃 생성
        //res - layout디렉터리 우클릭 - New - Layout Resource File
        //item_viewpager 파일 생성

        //2
        //뷰페이저에 사용할데이터(텍스트뷰의 값) 생성 후 변수(testList)생성하여 담기
        val textList = listOf("뷰1","뷰2","뷰3","뷰4")

        //2-1
        //데이터와 뷰페이저를 연결해줄 어댑터인 커스텀 어댑터 생성
        val customAdapter = CustomPagerAdapter()

        //2-2
        //어댑터에 있는 textList변수에 데이터 전달(오버라이드)
        customAdapter.textList = textList

        //2-3
        //뷰페이저에 어댑터 연결
        binding.viewPager.adapter = customAdapter

        //3
        //탭레이아웃에 메뉴명으로 사용할 이름들 배열에 저장
        val tabTitle = listOf("탭1","탭2","탭3","탭4")

        //3-1
        //TabLayoutMediator를 사용하여 탭레이아웃과 뷰페이저 연결
        //코드블록으로 전달되는 tab파라미터의 text속성에 메뉴명 입력하고
        //마지막으로 attach()메서드를 호출하여 적용
        TabLayoutMediator(binding.tabLayout, binding.viewPager){tab, position ->
            tab.text = tabTitle[position]
        }.attach()

    }//onCreate
}//MainActivity

 

-activity_main.xml 

<?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">

<!--  어댑터를 연결할 화면  -->
<!--  뷰페이저와 탭레이아웃 추가...  -->
    <com.google.android.material.tabs.TabLayout
        android:id="@+id/tabLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_constraintBottom_toTopOf="@+id/viewPager"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/tabLayout" />

<!--  MainActivity.kt 에서 모두 연결...  -->

</androidx.constraintlayout.widget.ConstraintLayout>

 

-item_viewpager.xml

<?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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

<!--  텍스트 뷰 생성  -->
    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="뷰의 제목"
        android:textSize="36dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

<!--  아이템 뷰를 사용하는 어댑터 생성...  -->
<!--  java밑 패키지명 우클릭 - New - Kotlin Class/File  -->
<!--  Class로 CustomPagerAdapter 생성  -->

</androidx.constraintlayout.widget.ConstraintLayout>

 

-CustumPagerAdapter.kt

//1
//item_viewpager를 사용하는 어댑터
//RecyclerView.Adapter를 상속받아 사용
//상속 받기 전 RecyclerView.ViewHolder를 상속받는 클래스 생성

//2
////RecyclerView.Adapter를 상속받고 제네릭으로 Holder클래스 지정
class CustomPagerAdapter: RecyclerView.Adapter<Holder>() {

    //2-2
    //어댑터에서 사용할 textList변수 선언 후 배열로 초기화
    //각 페이지에서 보여줄 텍스트 전달, 나중에 activity에서 오버라이드하여 값 입력 함
    var textList = listOf<String>()

    //2-1
    //3개 메서드 오버라이드
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
        //2-4
        //바인딩 생성 후 Holder클래스에 전달
        val binding = ItemViewpagerBinding.inflate(LayoutInflater.from(parent.context), parent, false)
        return Holder(binding)
    }

    override fun onBindViewHolder(holder: Holder, position: Int) {
        //2-5
        //textList의 값 중 현재 포지션 값을 변수 text를 만들어 저장하고
        //Holder 클래스의 setText()메서드 호출, 변수 값 파라미터로 전달하여 화면에 출력
        val text = textList[position]
        holder.setText(text)
    }

    override fun getItemCount(): Int {
        //2-3
        //페이지 개수 결정하여 반환
        return textList.size
    }

    //3
    //어댑터를 연결할 화면 작성
    //activity_main.xml 파일 수정

}

//1-1
//RecyclerView.ViewHolder를 상속받는 클래스(Holder) 생성
//홀더 클래스의 binding 파라미터로 onCreateViewHoler에서 생성할 바인딩 전달
//홀더에서 binding을 전역변수로 사용하기 위해 val키워드 필수***
class Holder(val binding: ItemViewpagerBinding): RecyclerView.ViewHolder(binding.root){

    //1-2
    //메서드(setText())를 만들어 item_viewpager레이아웃의 텍스트뷰에 값을 입력하는 코드 작성
    //setText()메서드의 파라미터는 가상으로 text:String으로 미리 정의
    fun setText(text:String){

        //문자열(String)을 받는 변수 text의 값을 전달받아서 레이아웃 텍스트뷰에 값을 넣음
        binding.textView.text = text
    }

}

 

 

-결과

 

 


이 포스팅에 작성한 내용은 고돈호, ⌜이것이 안드로이드다⌟, 한빛미디어(주), 2022 에서 발췌하였습니다.