안녕하세요~ 챠니입니다! :)
오늘은 ViewPager2 + TabLayout를 활용하여 스와아프 뷰(Swipe View)를 만드는 방법에 대해서 알아보겠습니다.
1. gradle 설정
먼저 필요한 ViewBinding 및 viewpager2를 dependencies에 추가합니다.
추가하는 코드는 주석설명을 달아놓았습니다.
plugins {
id 'com.android.application'
id 'org.jetbrains.kotlin.android'
}
android {
compileSdk 32
defaultConfig {
applicationId "com.example.viewpager2_tablayout_kotlin"
minSdk 23
targetSdk 32
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
kotlinOptions {
jvmTarget = '1.8'
}
//====== ViewBinding 설정
buildFeatures{
viewBinding true
dataBinding true
}
}
dependencies {
implementation 'androidx.core:core-ktx:1.7.0'
implementation 'androidx.appcompat:appcompat:1.4.2'
implementation 'com.google.android.material:material:1.6.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.3'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
//====== ViewPager2
implementation 'androidx.viewpager2:viewpager2:1.0.0'
}
2. 레이아웃
Main Layout(메인레이아웃) 구성도 입니다.
아래쪽에는 TabLayout이 위쪽에는 ViewPager2를 배치하였습니다.
<?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">
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vp_viewpager_main"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/tl_navigation_view"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.tabs.TabLayout
android:id="@+id/tl_navigation_view"
android:layout_width="match_parent"
android:layout_height="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
3. 프래그먼트(Fragment) 생성
ViewPager2안에 들어갈 Fragment를 만들어줍니다.
각 Fragment는 ViewBinding을 활용하여 Binding합니다.
[Tab1]
// Tab1Fragment.kt
class Tab1Fragment : Fragment() {
private var _binding: FragmentTab1Binding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, ): View? {
_binding = FragmentTab1Binding.inflate(inflater, container, false)
return binding.root
}
}
<?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"
android:background="#80FF0000"
tools:context=".Tab1Fragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Hello Fragment1!!"
android:textColor="@color/white"
android:textSize="40dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
[Tab2]
// Tab2Fragment.kt
class Tab2Fragment : Fragment() {
private var _binding: FragmentTab2Binding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, ): View? {
_binding = FragmentTab2Binding.inflate(inflater, container, false)
return binding.root
}
}
<?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"
android:background="#8000FF00"
tools:context=".Tab1Fragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Hello Fragment2!!"
android:textColor="@color/white"
android:textSize="40dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
[Tab3]
// Tab3Fragment.kt
class Tab3Fragment : Fragment() {
private var _binding: FragmentTab3Binding? = null
private val binding get() = _binding!!
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?, ): View? {
_binding = FragmentTab3Binding.inflate(inflater, container, false)
return binding.root
}
}
<?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"
android:background="#800000FF"
tools:context=".Tab1Fragment">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center"
android:text="Hello Fragment3!!"
android:textColor="@color/white"
android:textSize="40dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
4. ViewPager2Adapter 및 연결
다음은 ViewPager2 Adapter를 생성하여 ViewPager2에 연결 및 컴파일을 해보겠습니다.
아래는 MainActivity 코드입니다.
//MainActivity.kt
class MainActivity : AppCompatActivity() {
lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
initViewPager()
}
private fun initViewPager() {
//ViewPager2 Adapter 셋팅
var viewPager2Adatper = ViewPager2Adapter(this)
viewPager2Adatper.addFragment(Tab1Fragment())
viewPager2Adatper.addFragment(Tab2Fragment())
viewPager2Adatper.addFragment(Tab3Fragment())
//Adapter 연결
binding.vpViewpagerMain.apply {
adapter = viewPager2Adatper
registerOnPageChangeCallback(object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)
}
})
}
//ViewPager, TabLayout 연결
TabLayoutMediator(binding.tlNavigationView, binding.vpViewpagerMain) { tab, position ->
Log.e("YMC", "ViewPager position: ${position}")
when (position) {
0 -> tab.text = "Tab1"
1 -> tab.text = "Tab2"
2 -> tab.text = "Tab3"
}
}.attach()
}
}
아래는 ViewPager2 Adapter코드입니다.
//ViewPager2Adapter.kt
class ViewPager2Adapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
var fragments: ArrayList<Fragment> = ArrayList()
override fun getItemCount(): Int {
return fragments.size
}
override fun createFragment(position: Int): Fragment {
return fragments[position]
}
fun addFragment(fragment: Fragment) {
fragments.add(fragment)
notifyItemInserted(fragments.size - 1)
//TODO: notifyItemInserted!!
}
fun removeFragement() {
fragments.removeLast()
notifyItemRemoved(fragments.size)
//TODO: notifyItemRemoved!!
}
}
5. 결과물
다음은 ViewPager2 Adapter를 생성하여 ViewPager2에 연결 및 컴파일을 해보곘습니다.
코드에 문제가 없다면 다음과 같은 결과물을 얻을 수 있습니다.
글 정리 & 소스코드
[소스코드]
ViewPager2+TabLayout:
https://github.com/younminchan/kotlin-study/tree/main/ViewPager2_TabLayout_kotlin
질문 또는 궁굼한 부분은 댓글을 남겨주세요! 친절하게 답변드리겠습니다!
응원의 댓글은 저에게 큰 힘이 된답니다! :)
즐거운 하루되세요!
깃허브 보러 놀러오세요 👇 (맞팔환영)
https://github.com/younminchan
'🖥 Programming > 📱 Android (Kotlin)' 카테고리의 다른 글
[Android][kotlin] EditText Filter(필터) 적용, 한글만, 영어만, 특수문자 제한 등 예제 (0) | 2022.07.16 |
---|---|
[kotlin] hideKeyboard, showKeyboard(키보드 내리기, 키보드 올리기, 키보드 숨기기, 키보드 자동 내리기, 키보드 자동올리기) (0) | 2022.07.15 |
[kotlin] java.net.UnknownHostException / No address associated with hostname 에러 해결 (0) | 2022.07.14 |
[android] Task :app:compileDebugJavaWithJavac FAILED 오류 해결방법 (0) | 2022.07.13 |
[안드로이드] 앱 초기 로딩시 흰 화면 없애기(인트로 페이지 공백없애기)(intro, splash) (0) | 2022.07.04 |
[kotlin][android] 토스트메세지(Toast msg) 중복 방지 (0) | 2022.06.17 |
[Android][kotlin] Android jetpack WorkManager (작업예약, 백그라운드 ) (1) | 2022.05.13 |
[Android][kotlin] Glide 이미지 캐시 및 preload 알아보기 (0) | 2022.05.11 |