0. ViewPager 에 대해서 알아보자.
- ViewPager?
각 View 가 책의 페이지처럼 보여지고 슬라이드 시, 마치 책을 넘기는 듯한 효과를 나타내고자 할때 쓰이는 Component 이다.
한, 화면에 모든것을 다 보여주지 못하고 여러 페이지로 나누어 보여주고자할때 사용하면 된다.
- about. ViewPager Version
현재 시점에서 ViewPager를 사용하려면 Android Studio에서 기본으로 ViewPager2를 사용하도록 되어있다.
버전 히스토리를 살펴보자면 현재는 ViewPager2:1.1.0 까지 업데이트 됬다.
이전 ViewPager를 사용해본적은 없으나 문서를 찾아보면 사용하기가 다소 까다롭고 버그 이슈도 있었던듯하다. 해서 구글에서 라이브러리가 Androidx로 바뀌는 과정에서 ViewPager2가 나오게 됬고 첫 1.0.0-alpha 버전이 2019.02.07에 발표되어 지금까지 업데이트가 되었음을 알수 있다.
-> ViewPager2 Version 내역 확인 참고 링크는 여기!!
- ViewPager2 에서 개선된 점 (관련 링크 -> Migrating from ViewPager to ViewPager2)
- Vertical scrolling : 기존 가로 페이징은 물론 세로 페이징도 지원한다.
- Right-to-left support : 언어에 따라 LTR, RTL이 자동 설정되고, android:layoutDirection 속성을 통해 수동으로도 설정가능하다.
- modifiable Fragment collenctions : 프래그먼트의 변화를 동적으로 반영하는 것이 가능하다. 기본 컬렉션이 변경되면 notifyDatasetChanged()를 호출하여 UI를 업데이트한다. 즉, 앱은 런타임 시 프래그먼트 컬렉션을 동적으로 수정할 수 있고, 그러면 ViewPager2는 수정된 컬렉션을 올바르게 표시한다.
- DiffUtil : Recyclerview의 DiffUtil을 사용 가능하다. ViewPager2는 RecyclerView를 기반으로 빌드되므로 DiffUtil 유틸리티 클래스에 액세스할 수 있고 이에 따른 애니메이션을 활용할 수 있다.
- 마지막으로 가장중요한점으로
기존 ViewPager는 더이상 관리,개발되지 않는다.즉 더이상의 업데이트는 없다는 말! 고로 앞으로는 지속 업데이트, 개발중인 ViewPager2 만 사용하도록 하자.
1. 기능 구현
- 화면 상단에 TabLayout을 배치하고 Icon을 넣어보자
- 나머지 화면을 ViewPager2를 이용한 Fragment로 구성해보자.
2. Android Studio에서 기본 프로젝트(with empty activity) 생성하자!
생성시 'Empty Activity'로 기본 생성
3. ViewBinding 사용을 위한 build.gradle 설정
android {
// 뷰 바인딩 옵션 활성화
viewBinding {
enabled = true
}
}
4. activity_main.xml
- 화면구성 (Component Tree) 를 다음과 같이 만들어보자
- 메인화면(ConstraintLayout) 상단에 TabLayout 배치 (3개의 TabItem-Monday,Tuesday,Wednesday 을 가진다)
- TabLayout 하단 나머지 화면에 ConstraintLayout 추가
- 추가한 ConstraintLayout 에 ViewPager2 배치 (Fragment를 통해 화면 전환될 영역)
<?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/tab_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@+id/constraint_pages"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Monday" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Tuesday" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Wednesday" />
</com.google.android.material.tabs.TabLayout>
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/constraint_pages"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/tab_layout">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
- 결과물
5-1. 프래그먼트 별 화면 구성
- tabItem 갯수에 맞게 간단하게 구별 가능한 화면(3개)을 만들어보자 (frag_monday, frag_tuesday, frag_wednesday)
- Ex) frag_monday
<?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">
<TextView
android:id="@+id/frag_monday"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="겨울시인 Frag (1)"
android:textColor="#0971EF"
android:textSize="34sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
5-2. 프래그먼트 별 화면 구성
- 기존에 만들어놓은 Fragment UI xml 파일을 ViewBinding을 통해 kt 파일과 매핑시켜 놓자.
(FragMondy.kt, FragTuesday.kt, FragWednesday.kt)
- Ex) FragMonday.kt
class FragMonday : Fragment() {
private lateinit var binding : FragMondayBinding
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
binding = FragMondayBinding.inflate(inflater, container, false)
return binding.root
}
}
6. ViewPager 어댑터 구현(Adapter)
- Adapter의 역할 : 보여질 메인화면에 Fragment를 ViewPager 형식으로 매핑시켜준다.
- getItemCount() : 총 페이징될 갯수를 return
- createFragment(position) : when 구문을 통해 분기, 각 Fragment로의 화면 전환이 실행된다.
private const val FRAG_NUMS = 3
class ViewPagerAdapter(fragmentActivity: FragmentActivity): FragmentStateAdapter(fragmentActivity) {
override fun getItemCount(): Int {
return FRAG_NUMS
}
override fun createFragment(position: Int): Fragment {
return when(position){
0 -> return FragMonday()
1 -> return FragTuesday()
else -> return FragWednesday()
}
}
}
참고 : 기존 ViewPager 와 비교해 ViewPager2 에서의 Adapter 구현 시, 변경된 사항은 다음과 같다.
- 상속
- 기존
PagerAdapter(deprecated) 를 사용했을 경우 -> RecyclerView.Adapter 를 사용- 기존
FragmentPagerAdapter(deprecated) 를 사용했을 경우 -> FragmentStateAdapter 를 사용- 기존
FragmentStatePagerAdapter(deprecated) 를 사용했을 경우 -> FragmentStateAdapter 를 사용- Get. 페이징 갯수 :
getCount(deprecated) -> getItemCount- Get .페이지:
getItem(deprecated) -> createFragment
7. MainActivity.kt
- tabTitleArray: TabLayout 의 Title 정보를 가진 array 준비
- tabIconArray :TabLayout 에 들어갈 Icon 가진 array 준비
sample icon 만드는법 링크 참고 -> 4. BottomNavigation 아이콘 만들기 (Vertor Asset-기본 제공)- viewPager.adapter = ViewPagerAdapter(this) : 만들어 놓은 Adapter를 ViewPager2 의 Adapter로 설정
- TabLayoutMediator : TabLayout과 ViewPager2의 연동을 도와주는 객체로 attach()를 통해 연동 완료
(구문 내 구현해야 할 것은 준비된 Array에서 Title 과 Icon을 가져와서 Mapping 작업)
class MainActivity : AppCompatActivity() {
private var mBinding : ActivityMainBinding? = null
private val binding get() = mBinding!!
private val tabTitleArray = arrayOf(
"Monday", "Tuesday", "Wednesday"
)
private val tabIconArray = arrayOf(
R.drawable.ic_baseline_arrow_back_24,
R.drawable.ic_baseline_arrow_downward_24,
R.drawable.ic_baseline_arrow_forward_24
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
var viewPager = binding.viewpager
var tabLayout = binding.tabLayout
viewPager.adapter = ViewPagerAdapter(this)
TabLayoutMediator(tabLayout, viewPager){
tab, position -> tab.text = tabTitleArray[position]
tab.icon = getDrawable(tabIconArray[position])
}.attach()
}
}
8. 추가 기능 (Scrollable)
- 본 예제에서는 Item(page) 항목이 3개라 상관없지만 Item이 엄청 많아진다면 한 화면에 표시되기 어렵다
해서 다수의 Item을 페이징할 경우, TabLayout이 스크롤이 가능하도록 할 수 있는데 방법은 다음과 같다.
- activity_main.xml 의 TabLayout 에 속성값(tabMode)을 주도록하자.
기본값인 fixed -> Scrollable 로 바꿔주기만 하면 끝!
9. 실행결과
페이징 방법(1) : TabLayout 의 Item 을 선택하기
페이징 방법(2) : ViewPager 영역을 슬라이드로 넘기기
10. Reference
- 주의할점
참고한 동영상 강의는 Java 로 진행된 강의입니다. Kotlin 을 공부하기 위한 목적으로 Java-Kotlin 간의 다른 부분에 대해서
직접 찾아가며 예제 작성을 하였고 영상이 올라온 시점이 3년 전이라 현재의 버전, API 들이 deprecated 된 경우도 있어
이 또한 현재 권장하는 API로 변경/적용 한 부분이 있어 Code가 다를 수 있으니 보시는 분들은 참고 바람.
'Android > Kotlin' 카테고리의 다른 글
[Android, Kotlin] TableLayout (0) | 2022.05.24 |
---|---|
[Android, Kotlin] RadioButton & CheckBox (0) | 2022.05.20 |
[Android, Kotlin] 레이아웃 (3) ConstraintLayout (0) | 2022.05.17 |
[Android, Kotlin] VideoView (0) | 2022.05.06 |
[Android, Kotlin] 레이아웃 (2) RelativeLayout (0) | 2022.05.06 |