1. Viewpager2
- ViewPager 라이브러리의 개선된 버전으로, 세로 페이징 (android:orientation="vertical")과 오른쪽에서 왼쪽 페이징 (android:layoutDirection="rtl")을 지원한다.
- 화면 슬라이드: 하나의 전체 화면에서 다른 전체 화면으로 전환하는 것
- Viewpager2 객체를 활용하여 스와이프로 화면 전환을 구현할 수 있다.
Viewpager2를 쓰기 위해서 build.gradle.kts (Module :app)에서 플러그인을 추가해줘야 한다.
dependencies {
implementation("androidx.viewpager2:viewpager2:1.0.0")
}
Viewpager2를 사용하기 위해 화면에 보여줄 프래그먼트 레이아웃과 클래스를 작성해주고, Viewpager2의 adpater를 만들어준다.
class MyPagerAdapter(fa: FragmentActivity) : FragmentStateAdapter(fa) {
// 외부에서 FragmentActivity를 받아와서 그걸 처리.
private val NUM_PAGES = 3
override fun getItemCount(): Int = NUM_PAGES
// 만들어줄 전체 페이지 수
override fun createFragment(position: Int): Fragment {
// 각 페이지가 어떤 프래그먼트로 만들어질지 내용 전해줌.
return when (position) {
0 -> { MyFragment.newInstance("Page 1", "")}
1 -> { MyFragment.newInstance("Page 2", "")}
else -> { MyFragment.newInstance("Page 3", "")}
}
}
}
activity_main.xml에서 메인 액티비티 화면을 구성하는데 여기서 뷰페이저를 배치해준다. 다음으로 구현할 TabLayout을 위해 viewpager 아래에 appBarLayout을 배치하고 그 안에 TabLayout을 배치해주었다.
<?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:layout_width="0dp"
android:layout_height="0dp"
android:id="@+id/viewpager"
android:orientation="horizontal"
app:layout_constraintBottom_toTopOf="@+id/appBarLayout"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<com.google.android.material.appbar.AppBarLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:id="@+id/appBarLayout"
android:theme="@style/Theme.AppCompat.Light.DarkActionBar"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<com.google.android.material.tabs.TabLayout
android:layout_width="match_parent"
android:layout_height="60dp"
android:id="@+id/tabs"
android:background="@color/white"
app:tabIndicatorColor="@color/design_default_color_primary"
app:tabRippleColor="@color/design_default_color_primary"
app:tabSelectedTextColor="@color/design_default_color_primary"
app:tabTextColor="@color/black"/>
</com.google.android.material.appbar.AppBarLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
MainActivity 클래스에서 뷰페이저 어뎁터를 연결시켜준다. setPageTransformer 함수를 이용하여 화면 슬라이드 애니메이션 설정을 할 수 있다. 구글에서 ZoomOutPageTransformer, DepthPageTransformer 와 같이 전환 효과를 구현할 수 있는 코드를 공개하고 있다. 이를 복사해서 클래스를 만들고 활용하면 보다 더 풍부한 화면 전환 효과를 나타낼 수 있다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
// 어뎁터 설정
binding.viewpager.apply {
adapter = MyPagerAdapter(context as FragmentActivity)
// MyPagerAdapter 객체 만들어서 뷰페이저 어뎁터 속성에 연결
setPageTransformer(ZoomOutPageTransformer())
// 페이지 슬라이드 효과
}
}
}
2. TabLayout
- TabLayout을 사용하면 탭을 가로로 나타낼 수 있다.
- Viewpager와 TabLayout을 함께 사용하면 스와이프 뿐만 아니라 탭 버튼을 통해서도 화면 전환이 가능하다.
- 탭으로 어떤 페이지에 있는지 직관적으로 알 수 있도록 하여 탐색의 용이성을 제공한다.
메인 액티비티 레이아웃에 TabLayout을 배치한다. 이에 대한 코드는 위의 1번 내용에 있다.
TabLayout을 사용하기 위해 MainActivity 클래스에 TabLayoutMediator를 사용한다. 메뉴 바를 나타내기 위해 res>drawable 에 아이콘을 추가하고 배열에 넣어준다.
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
// 메뉴 바 아이콘 배열
private val tabIcon = listOf(
R.drawable.ic_baseline_format_list_bulleted_24,
R.drawable.ic_baseline_map_24,
R.drawable.ic_baseline_info_24
)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.viewpager.apply {
adapter = MyPagerAdapter(context as FragmentActivity)
setPageTransformer(ZoomOutPageTransformer())
}
// 탭 레이아웃과 뷰페이저2를 연결할 때 TabLayoutMediator 씀.
TabLayoutMediator(binding.tabs, binding.viewpager) { tab, position ->
tab.text = "Title $position"
tab.setIcon(tabIcon[position]) // 포지션에 따라 서로 다른 아이콘을 가져오도록, 탭에 아이콘을 지정하기 위해 setIcon 함수 이용.
}.attach()
}
}
3. Navigation View
바텀 네비게이션을 구현하기 위해 build.gradle.kts (Module :app)에서 플러그인을 추가해준다.
dependencies {
// 메테리얼 디자인
implementation("com.google.android.material:material:1.10.0")
}
메인 액티비티 레이아웃에 바텀 네비게이션을 배치해준다. 그리고 activity_main.xml과 같은 위치인 res>layout에 프래그먼트 레이아웃을 원하는 개수만큼 만든다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
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"
android:background="#D8D8D8">
<FrameLayout
android:id="@+id/fragments_frame"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@+id/bottom_nav"
android:layout_centerHorizontal="true"
android:background="@color/design_default_color_primary"/>
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/bottom_nav"
app:menu="@menu/bottom_nav_menu"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:background="#fff"
app:labelVisibilityMode="unlabeled"
app:itemIconSize="40dp" />
</RelativeLayout>
다음은 프래그먼트 클래스 중 하나의 코드이다. 외부에서 접근할 때 메모리에 올린 것을 가져오기 위해 compation object 안에 fragment 인스턴스를 만들어 반환하는 코드를 넣어준다.
class HomeFragment : Fragment() {
companion object {
// Fragment 인스턴스를 만들어 반환
fun newInstance() : HomeFragment {
return HomeFragment()
}
}
// 메모리에 올라갔을 때
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
}
// 프래그먼트를 안고 있는 액티비티에 붙었을 때
override fun onAttach(context: Context) {
super.onAttach(context)
}
// 뷰가 생성되었을 때
// 프래그먼트와 레이아웃을 연결시켜주는 부분이다.
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
val view = inflater.inflate(R.layout.fragment_home, container, false)
return view
}
}
다음은 메인 액티비티 클래스 코드이다. 바텀 네비게이션에서 버튼이 클릭되었을 때 메인 액티비티에서 반응을 할 수 있도록 BottomNavigation.OnNavigationItemSelectedListener를 추가한다. 버튼이 클릭되었을 때 그에 해당하는 프래그먼트를 보여주기 위해 리스너 안에 supportFragmentManager를 사용하여 교체 설정을 넣는다. 초기 화면에는 홈 화면이 나타나도록 add를 사용한다.
class MainActivity : AppCompatActivity(){
private var mBinding: ActivityMainBinding? = null
private val binding get() = mBinding!!
private lateinit var homeFragment: HomeFragment
private lateinit var rankingFragment: RankingFragment
private lateinit var profileFragment: ProfileFragment
// 메모리에 올라갔을 때
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
mBinding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
binding.bottomNav.setOnNavigationItemSelectedListener(onBottomNavItemSelectedListener)
// 초기 화면으로 HomeFragment를 추가하여 표시
homeFragment = HomeFragment.newInstance()
supportFragmentManager.beginTransaction().add(R.id.fragments_frame, homeFragment).commit()
}
// 바텀네비게이션 아이템 클릭 리스너 설정
private val onBottomNavItemSelectedListener = BottomNavigationView.OnNavigationItemSelectedListener {
when(it.itemId) {
R.id.menu_home -> {
homeFragment = HomeFragment.newInstance() // 프래그먼트를 가져옴.
supportFragmentManager.beginTransaction().replace(R.id.fragments_frame, homeFragment).commit()
// supportFragmentManager : 프래그먼트 관리
}
R.id.menu_ranking -> {
rankingFragment = RankingFragment.newInstance()
supportFragmentManager.beginTransaction().replace(R.id.fragments_frame, rankingFragment).commit()
}
R.id.menu_profile -> {
profileFragment = ProfileFragment.newInstance()
supportFragmentManager.beginTransaction().replace(R.id.fragments_frame, profileFragment).commit()
}
}
true
}
}
<참고>
https://developer.android.com/training/animation/screen-slide-2?hl=ko
https://developer.android.com/guide/navigation/navigation-swipe-view-2?hl=ko
https://cliearl.github.io/posts/android/viewpager2-tablayout/
'Group Study (2023-2024) > Android 입문' 카테고리의 다른 글
[Android 입문] 5주차 스터디 - RoomDB, SharedPreferences, Datastore (0) | 2023.12.25 |
---|---|
[Android 입문] 3주차 스터디 -ListView, RecyclerView, ListView와 RecyclerView의 차이점 (1) | 2023.11.20 |
[Android 입문] 2주차 스터디 -Activity와 Fragment, ViewBinding (0) | 2023.11.13 |
[Android 입문] 1주차 스터디 -View와 Layout (0) | 2023.11.07 |