📌 학습 목표
- BottomNavigationView을 구성하고 사용할 수 있다.
- TabLayout을 구성하고 사용할 수 있다.
- ViewPager를 구성하고 사용할 수 있다.
📝 Standard Mission
1. BottomNavigationView를 이용해서 3개 이상의 Fragment를 오고가는 Activity 구현하기
- 각각 다른 아이콘 적용
- 각각 다른 Fragment로 이동하도록 적용
- Fragment 내용은 자유
- 단순하게 구성해도 됨 (ex. Fragment 1, Fragment 2와 같이 TextView 배치)
먼저, bottomNavigationView에 들어갈 메뉴 4개(홈, 설정, 알림, 마이페이지)를 넣어준다.
menu/menu_bottomnav.xml
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_home"
android:title="홈"
android:icon="@drawable/ic_baseline_home_24" />
<item
android:id="@+id/menu_setting"
android:title="설정"
android:icon="@drawable/ic_baseline_settings_24" />
<item
android:id="@+id/menu_alarm"
android:title="알림"
android:icon="@drawable/ic_baseline_notifications_24" />
<item
android:id="@+id/menu_mypage"
android:title="마이페이지"
android:icon="@drawable/ic_baseline_person_24" />
</menu>
HomeFragment (SettingFragment, AlarmFragment, MypageFragment 동일)
package com.example.homework6_1
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.example.homework6_1.databinding.FragmentHomeBinding
class HomeFragment: Fragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
return FragmentHomeBinding.inflate(layoutInflater).root
}
}
첫 화면을 home화면으로 설정해준다.
그리고 setOnItemSelectedListener를 통해 id에 따라서 Fragment를 교체한다.
MainActivity.kt
package com.example.homework6_1
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import com.example.homework6_1.databinding.ActivityMainBinding
class MainActivity : AppCompatActivity() {
private val binding:ActivityMainBinding by lazy {
ActivityMainBinding.inflate(layoutInflater)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
// 처음에 어떤 화면을 기본으로 할지
supportFragmentManager
.beginTransaction()
.replace(binding.containerFragment.id, HomeFragment())
.commitAllowingStateLoss()
// run(범위함수) 사용하면 navBottom 바로 쓸 수 있음
binding.navBottom.run {
setOnItemSelectedListener {
when (it.itemId) {
R.id.menu_home -> {
supportFragmentManager
.beginTransaction()
.replace(binding.containerFragment.id, HomeFragment())
.commitAllowingStateLoss()
}
R.id.menu_setting -> {
supportFragmentManager
.beginTransaction()
.replace(binding.containerFragment.id, SettingFragment())
.commitAllowingStateLoss()
}
R.id.menu_alarm -> {
supportFragmentManager
.beginTransaction()
.replace(binding.containerFragment.id, AlarmFragment())
.commitAllowingStateLoss()
}
R.id.menu_mypage -> {
supportFragmentManager
.beginTransaction()
.replace(binding.containerFragment.id, MypageFragment())
.commitAllowingStateLoss()
}
}
true
}
selectedItemId = R.id.menu_home // 초기에 설정한 것을 navBottom 에 알려주기 위해
}
}
}
Fragment가 들어갈 FrameLayout를 배치하고, menu가 들어갈 BottomNavigationView를 배치해준다.
BottomNavigationView에는 menu를 연결해주는 것을 잊으면 안 된다!
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">
<FrameLayout
android:id="@+id/container_fragment"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@id/nav_bottom"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/nav_bottom"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/container_fragment"
app:menu="@menu/menu_bottomnav" />
</androidx.constraintlayout.widget.ConstraintLayout>
2. 1번 과제에서 만들었던 Fragment중 하나에 TabLayout과 ViewPager2를 사용하여 슬라이드로 Fragment 바꾸는 화면 구현해보기
- Tab 3개 이상 구현하기
- 각 Tab마다 다른 Fragment 띄우기
일단, ViewPager2를 사용하기 위해선 gradle 파일을 수정해줘야 한다. 아래 코드를 작성하고 Sync Now를 해준다!
build.gradle
Home Fragment에 TabLayout과 ViewPager2를 배치해준다.
fragment_home.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">
<com.google.android.material.tabs.TabLayout
android:id="@+id/tab_home"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintBottom_toTopOf="@id/vp_home"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/vp_home"
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/tab_home" />
</androidx.constraintlayout.widget.ConstraintLayout>
다음으로, Adapter를 만들어준다.
HomeVPAdapter.kt
package com.example.homework6_1
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
class HomeVPAdapter(fragment: Fragment): FragmentStateAdapter(fragment) {
// 총 아이템의 개수
override fun getItemCount(): Int = 3
// position 에 따라서 어떤 fragment 를 보여줄지 설정
override fun createFragment(position: Int): Fragment {
return when(position) {
0 -> OneFragment()
1 -> TwoFragment()
2 -> ThreeFragment()
else -> OneFragment()
}
}
}
HomeFragment에 Adapter를 연결해준다.
HomeFragment.kt
package com.example.homework6_1
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import androidx.viewpager2.widget.ViewPager2
import com.example.homework6_1.databinding.FragmentHomeBinding
import com.google.android.material.tabs.TabLayoutMediator
class HomeFragment: Fragment() {
private lateinit var binding: FragmentHomeBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentHomeBinding.inflate(layoutInflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
// fragment view 생성이 된 후 viewPager2 setting
val homeVPAdapter = HomeVPAdapter(this)
binding.vpHome.adapter = homeVPAdapter
val tabTitleArray = arrayOf(
"One",
"Two",
"Three",
)
// TabLayout 연동
TabLayoutMediator(binding.tabHome, binding.vpHome) { tab, position ->
tab.text = tabTitleArray[position]
}.attach() // 연결 최종
}
}
📝 Fragment에 adapter 연결하는 법
원래는 Activity에 연결했지만, 처음으로 fragment에 연결하게 돼서 많이 헤맸었다.
처음에는 onCreateView에 바로 adapter를 연결해줬는데 view가 생성되기 전이라 그런지 화면에 아무것도 뜨지 않았었다. 그래서 Fragment의 생명주기에 대해 찾아봤는데, onCreateView로 view가 생성된 이후에 onViewCreated에서 viewPager2를 adapter로 셋팅해야되는 것을 알게 됐다!
📌 프로젝트 파일 구성
'🍞 대외활동 > Univ Makeus Challenge' 카테고리의 다른 글
[UMC] Android 8주차 워크북 (Database) (0) | 2022.11.21 |
---|---|
[UMC] Android 7주차 워크북 (Thread) (0) | 2022.11.17 |
[UMC] Android 5주차 워크북 (RecyclerView) - 메모장 앱 (0) | 2022.10.24 |
[UMC] Android 5주차 워크북 (ListView) (0) | 2022.10.23 |
[UMC] Android 4주차 워크북 (LifeCycle) (0) | 2022.10.18 |