BottomNavigationView란
BottomNavigationView란 무엇이고 어떤 기능
뜻 :
- 화면 맨 위나 맨 밑에 있는 네비게이션 역할을 하는 버튼 모음
- fragment를 활용해서 각각 다른 화면들을 보여줄 때 사용
- 각각의 버튼을 눌렀을 때 레이아웃에 fragment를 붙일 수 있음
- 안드로이드 support Library 25 이상부터 지원
기능 :
- 각 탭 선택 시 fragment를 전환함
BottomNavigationView가 사용된 예시
1. 카카오톡

2. FLO

BottomNavigationView의 구성 요소
BottomNavigationView를 사용하려면 레이아웃에 추가를 해야함. 이때 어떤 값들이 필수적으로 지정?
기본 레이아웃 :
<com.google.android.material.bottomnavigation.BottomNavigationView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schema.android.com/apk/res/res-auto"
android:id="@+id/navigation"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_gravity="start"
app:menu="@menu/my_navigation_items" />
기타 참고사항 :
- 빈틈 없이 뷰에 딱 맞게 들어가도록 0으로 설정
android:layout_marginEnd="0dp"
android:layout_marginStart="0dp"
- 아래 부분으로 위치
android:layout_gravity="bottom"
- 배경색 지정
android:background="@color/background"
- 참조할 메뉴의 경로
app:menu="@menu/menu_bottom"
Menu 리소스 XML
<menu> 태그는 무엇
- 필수사항
- 메뉴 항목의 컨테이너인 Menu를 정의
- <menu> 요소는 루트 노드여야 하고 하나 이상의 <item>과 <group> 요소를 보유할 수 있음
<item> 태그는 무엇
- 메뉴 내 단일 항목을 나타내는 MenuItem을 생성
- 이 요소는 하위 메뉴를 생성하기 위한 중첩 <menu> 요소를 포함할 수 있음
- <group> :
- <item> 요소를 위한 투명 컨테이너 (선택사항)
- 이 컨테이너를 사용하면 메뉴 항목을 분류하여 활성 상태와 가시성 등의 속성을 공유할 수 있음
<item>태그에 설정할 수 있는 항목 무엇
android:id
- 항목에 고유한 리소스 ID
- 새 리소스 ID를 만들려면 "@+id/name" 양식을 사용
- 사용자가 항목을 선택하면 애플리케이션이 이 ID를 통해 해당 항목을 인식
android:icon
- 항목의 아이콘으로 사용할 수 있는 드로어블에 관한 참조
android:title
- 항목의 제목으로 사용할 문자열에 관한 참조
android:showAsAction
- 항목이 앱 바에서 작업 항목으로 표시되어야 하는 시기와 방법을 지정
android:titleCondensed
- 문자열 리소스
- 문자열 리소스 또는 원시 문자열로 요약된 제목
- 이 제목은 일반 제목이 너무 긴 경우에 사용
android:onClick
- 메서드 이름
- 이 메뉴 항목을 클릭하면 호출할 메서드
- 이 메서드는 활동에서 공개로 선언해야 함
- MenuItem이 유일한 매개변수로 허용되며, 이는 클릭한 항목을 나타남
- 이 메서드는 onOptionsItemSelected() 표준 콜백보다 우선
- API 수준 11에 도입
android:actionLayout
- 레이아웃 리소스
- 작업 뷰로 사용할 레이아웃
- API 수준 11에 도입
화면구성
1. 왼쪽의 예시 화면에서 (A)와 (B)에 해당하는 각각의 알맞은 화면 구성 요소를 선택
- (A) = Activity / Fragment
- (B) = Activity / Fragment
2. 왼쪽 화면을 구성하기 위해서 일반적으로 몇 개의 Fragment가 필요한가
- 정답 ) 3 개
BottomNavigationView 설정하기
각 Item을 클릭했을 때 나타나는 이벤트 설정하기
1. 원하는 activity 레이아웃 xml에 BottomNavigationView 추가
<com.google.android.material.bottomnavigation.BottomNavigationView
android:id="@+id/main_bnv"
android:layout_width="match_parent"
android:layout_height="56dp"
android:layout_gravity="start"
app:menu="@menu/bottom_nav_menu" />
2. res - menu 폴더에 원하는 menu xml 생성
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/action_search"
android:title="@string/menu_search"
android:icon="@drawable/ic_search" />
<item android:id="@+id/action_settings"
android:title="@string/menu_settings"
android:icon="@drawable/ic_add" />
<item android:id="@+id/action_navigation"
android:title="@string/menu_navigation"
android:icon="@drawable/ic_action_navigation_menu" />
</menu>
3. 각 메뉴에 해당되는 Fragment 생성
class SearchFragment : Fragment() {
lateinit var binding: FragmentSearchBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentSearchBinding.inflate(inflater, container, false)
return binding.root
}
}
4. MainActivity.kt와 Fragment 연결 추가
supportFragmentManager.beginTransaction()
.replace(R.id.main_frm, HomeFragment())
.commitAllowingStateLoss()
binding.mainBnv.setOnItemSelectedListener{ item ->
when (item.itemId) {
R.id.action_search -> {
supportFragmentManager.beginTransaction()
.replace(R.id.main_frm, SearchFragment())
.commitAllowingStateLoss()
return@setOnItemSelectedListener true
}
R.id.action_settings -> {
supportFragmentManager.beginTransaction()
.replace(R.id.main_frm, SettingFragment())
.commitAllowingStateLoss()
return@setOnItemSelectedListener true
}
R.id.action_navigation -> {
supportFragmentManager.beginTransaction()
.replace(R.id.main_frm, NavigationFragment())
.commitAllowingStateLoss()
return@setOnItemSelectedListener true
}
}
false
}
BottomNavigationView의 주요 속성들을 정리
각 Item을 클릭했을 때 나타나는 이벤트 설정 방법 꼭 정리
// transaction 호출하기 위한 코드
supportFragmentManager.beginTransaction()
.replace(R.id.main_frm, HomeFragment())
.commitAllowingStateLoss()
아이템 골랐을 때
binding.mainBnv.setOnItemSelectedListener{ item ->
when (item.itemId) {
// 검색 아이콘일때
R.id.action_search -> {
supportFragmentManager.beginTransaction()
.replace(R.id.main_frm, SearchFragment()) // SearchFragment로 대체
.commitAllowingStateLoss() // 적용
return@setOnItemSelectedListener true
}
// 설정 아이콘일때
R.id.action_settings -> {
supportFragmentManager.beginTransaction()
.replace(R.id.main_frm, SettingFragment()) // settingFragment로 대체
.commitAllowingStateLoss() // 적용
return@setOnItemSelectedListener true
}
}
false
}
TabLayout
TabLayout이란 무엇이고 어떤 기능?
뜻 :
- 각각의 탭 메뉴
- 탭을 이용하여 겹쳐진 자식 중에서 하나를 선택하는 레이아웃
기능 :
- 상위에 탭 메뉴를 구현
- 탭을 표시할 수 있는 수평 레이아웃을 제공
- 화면 전환을 위해 ViewPager와 함께 사용
TabLayout이 사용된 예시
1. FLO

2. 구글 플레이 스토어

TabLayout에서 사용할 수 있는 속성들은 무엇
app:tabTextColor="색상"
- 기본 텍스트 색상
app:tabSelectedTextColor="색상"
- 선택된 텍스트 색상
android:layout_height="높이dp"
- 탭 전체 높이
app:tabGravity="fill"
- 탭 전체 너비
android:background="색상"
- 탭 배경 색상
app:tabIndicatorColor="색상"
- 밑줄 색상
app:tabIndicatorHeight="높이dp"
- 밑줄 두께
app:tabIndicatorGravity="top | center | bottom | stretch"
- 밑줄 위치
android:icon="@drawable/아이콘이름"
- 아이콘 설정
ViewPager2
ViewPager란 무엇이고 어떤 기능
뜻 :
- 화면에 표시될 컨텐츠를 전환하는 방법
- 데이터를 페이지 단위로 표시하고, 좌/우 뒤집기(flip)을 통해 페이지를 전환할 수 있도록 만들어주는 컨테이너
기능 :
- 여러 종류의 뷰(View) 위젯을 사용하여 각 뷰페이저의 페이지를 구성
- 데이터를 "페이지 단위"로 화면에 표시
ViewPager가 사용된 예시에는 무엇
1. 쿠팡

2. 버커킹

ViewPager와 ViewPager2의 차이는 무엇
- ViewPager2는 ViewPager 라이브러리 개선된 버전
- ViewPager2는 ViewPager 사용시 발생하는 일반적인 문제를 해결
- ViewPager2는 적극적인 개발 지원을 받음
- ViewPager2는 가로페이징 뿐만 아니라 세로페이징도 제공함
- ViewPager2는 오른쪽에서 왼쪽 (RTL) 페이징을 제공함
- ViewPager2는 수정 가능한 Fragment 컬렉션을 통해 페이징을 지원
- ViewPager2는 기본 컬렉션이 변경되면 notifyDatasetChanged()를 호출하여 UI 업데이트함
- ViewPager2는 앱을 런타임 시 fragment 컬렉션으로 동적으로 수정할 수 있음
- ViewPager2는 RecyclerView를 기반으로 빌드되므로 DiffUtil 클래스에 엑세스하여 데이터세트 변경, 애니메이션 등을 활용할 수 있음
VIewPager2에서 사용할 수 있는 속성들은 무엇
android:id="@+id/viewPager1"
- id 설정
android:layout_width="match_parent"
- 넓이 설정
android:layout_height="0dp"
- 높이 설정
android:orientation="horizontal"
- 방향 설정
android:layoutDirection="rtl"
- 오른쪽에서 왼쪽으로 가기 설정
android:layout_weight="0.5"
- 무게 설정
ViewPager2 설정하기
ViewPager2를 이용하기 위해 어떤 라이브러리를 사용
XML에 들어가야 하는 속성도 작성
1. build.gradle 파일에 종속 항목 추가
- Groovy
dependencies {
implementation "androidx.viewpager2:viewpager2:1.0.0"
}
- Kotlin
dependencies {
implementation("androidx.viewpager2:viewpager2:1.0.0")
}
2. 사용할 레이아웃 xml에 Viewpager2 추가
<androidx.viewpager2.widget.ViewPager2
android:id="@+id/home_banner_vp"
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginTop="15dp"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
3. Viewpager2로 보여주고 싶은 내부용 xml 파일 생성
// fragment_banner.xml로 만듦
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto">
<ImageView
android:id="@+id/banner_image_iv"
android:layout_width="match_parent"
android:layout_height="100dp"
android:scaleType="fitXY"
android:src="@drawable/img_viewpager_exp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
4. Adapter 파일 생성
class BannerVPAdapter(fragment: Fragment) : FragmentStateAdapter(fragment) {
private val fragmentlist : ArrayList<Fragment> = ArrayList()
//사용할 Fragment 개수
override fun getItemCount(): Int = fragmentlist.size
//Fragment 생성
override fun createFragment(position: Int): Fragment = fragmentlist[position]
// Fragment 추가
fun addFragment(fragment: Fragment){
fragmentlist.add(fragment)
notifyItemInserted(fragmentlist.size-1)
}
}
5. ViewPager2로 보일 Fragment 생성
class BannerFragment(val imgRes : Int) : Fragment() {
// 보이고픈 레이아웃 뷰바인딩
lateinit var binding: FragmentBannerBinding
// 뷰 만들기
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentBannerBinding.inflate(inflater, container, false)
// 이미지 넣음
binding.bannerImageIv.setImageResource(imgRes)
return binding.root
}
}
6. ViewPager2를 가진 메인 Fragment에 추가
class MainFragment : Fragment() {
lateinit var binding: FragmentMainBinding
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
binding = FragmentMainBinding.inflate(inflater, container, false)
binding.mainViewPagerBtn.setOnClickListener {
(context as MainActivity).supportFragmentManager.beginTransaction()
.replace(R.id.main_frm, TempFragment())
.commitAllowingStateLoss()
}
val bannerAdapter = BannerVPAdapter(this)
bannerAdapter.addFragment(BannerFragment(R.drawable.img_viewpager_exp))
bannerAdapter.addFragment(BannerFragment(R.drawable.img_viewpager_exp2))
binding.mainBannerVp.adapter = bannerAdapter
binding.mainBannerVp.orientation = ViewPager2.ORIENTATION_HORIZONTAL
return binding.root
}
}
ViewPager2에서 FragmentStateAdapter는 무엇이고 어떤 기능?
- ViewPager2가 제공하는 어댑터 클래스
- 각 페이지를 프래그먼트로 구성하고 싶을 때 사용
getItemCount()
- FragmentStateAdapter는 RecyclerView.Adapter를 상속함
- RecyclerView.Adapter의 abstarct 함수는 하위 클래스에서 반드시 오버라이딩
- FragmentStateAdapter에서 getItemCount()를 오버라이딩하지 않고 있음
- FragmentStateAdapter 클래스를 상속하는 하위 클래스에서 오버라이딩 해줘야 함
- ViewPager2에서의 getItemCount()는 페이지 개수를 반환
createFragment()
- 파아미터 : position의 값
- 반환값 : Fragment 인스턴스
- position 별로 서로 다른 프래그먼트를 보여주기 위해 서로 다른 프래그먼트를 생성해서 반환
- 모든 position에 똑같은 프래그먼트를 보여줘야 하면 계속 같은 프래그먼트를 생성해서 반환하면 됨
ViewPager2 Indicator 설정하기
Indicator란 무엇이고 어떤 역할
- 하단 점
- viewPager 밑에 점처럼 생겨서 현재 몇번째 이미지를 보여주고 있는지 알려줌
ViewPager2에서 Indicator를 설정하려면 어떻게 해야하나
1. build.gradle에 설정 추가
dependencies {
implementation 'me.relex:circleindicator:2.1.6'
}
2. 원하는 레이아웃 xml의 viewPager 아래에 추가
<me.relex.circleindicator.CircleIndicator3
android:layout_width="match_parent"
android:layout_height="48dp"
app:ci_drawable="@color/purple"
app:ci_drawable_unselected="@color/gray"/>
3. ViewPager2 가진 메인 Fragment에 코드 추가
val indicator = binding.PannelIndicator
indicator.setViewPager(binding.PannelViewpager2)
참고 사이트 :
https://velog.io/@abc9985/AndroidBottomNavigationView-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EA%B8%B0
https://lktprogrammer.tistory.com/183
https://snakehips.tistory.com/104
https://everyshare.tistory.com/21
https://doitddo.tistory.com/88
https://angangmoddi.tistory.com/323
https://onlyfor-me-blog.tistory.com/425
https://colinch4.github.io/2020-11-25/BottomNavigationView/
https://velog.io/@abc9985/AndroidBottomNavigationView-%EB%A7%8C%EB%93%A4%EC%96%B4%EB%B3%B4%EA%B8%B0
https://curryyou.tistory.com/432
https://code-hyoon.tistory.com/11
https://parkjh7764.tistory.com/149
https://helloit.tistory.com/309
https://korean-otter.tistory.com/84
https://ppeper.github.io/android/android-viewpager2/
https://velog.io/@changhee09/%EC%95%88%EB%93%9C%EB%A1%9C%EC%9D%B4%EB%93%9C-ViewPager2
https://jgeun97.tistory.com/216
https://recipes4dev.tistory.com/148
https://onedaycodeing.tistory.com/211
https://todaycode.tistory.com/27
https://heechokim.tistory.com/23
'대외활동 > UMC 동아리' 카테고리의 다른 글
| [UMC 5기] Android 스터디 4주차 (0) | 2023.10.05 |
|---|---|
| [UMC 5기] Android 스터디 3주차 (0) | 2023.09.29 |
| [UMC 5기] Android 워크북 2주차 (1) | 2023.09.29 |
| [UMC 5기] Android 스터디 2주차 (0) | 2023.09.24 |
| [UMC 5기] Android 워크북 1주차 (0) | 2023.09.22 |