[Do it! 깡샘의 안드로이드 앱 프로그래밍 with 코틀린] 머티리얼 라이브러리
안드로이드 앱 프로그래밍에서 코틀린을 사용하여 머티리얼 디자인 라이브러리, 앱바, 코디네이터 레이아웃, 컬랩싱 툴바 레이아웃, 탭 레이아웃, 네비게이션 뷰, 확장된 플로팅 액션 버튼을 구현하는 방법을 설명한다. 각 섹션에서는 해당 컴포넌트의 설정 방법과 코드 예제를 제공하며, 상호작용 및 이벤트 처리 방법도 다룬다.
Aug 13, 2024
🌼앱바 사용하기
💡머티리얼 라이브러리란?
- 머티리얼 디자인은 모바일과 데스크톱, 그 밖에 다양한 장치를 아우르는 애플리케이션 디자인 지침이다.
- 머티리얼 라이브러리를 사용하려면 빌드 그래들 파일의 dependencies 항목에 선언해줘야 한다.
// 머티리얼 라이브러리 선언 implementation(libs.material)
💡앱바 레이아웃 - 화면 위쪽 영역 꾸미기
- 앱바란 화면 위쪽의 꾸밀 수 있는 영역이다.
- 앱바를 이용해 화면 위쪽 영역의 크기만 늘릴 수도 있지만 메뉴를 출력하는 툴바를 포함할 수도 있다.
- 툴바 이외에 이미지나 문자열을 함께 출력할 수도 있다.
- 앱바를 사용할 때는 대부분 앱바 레이아웃 안에 툴바를 포함한다.
// 앱바 레이아웃에 툴바 포함 <com.google.android.material.appbar.AppBarLayout android:id="@+id/appbar" (...생략...) > <androidx.appcompat.widget.Toolbar (...생략...) /> </com.google.android.material.appbar.AppBarLayout>
- layout_height 속성을 이용해 위쪽 영역을 크게 만들수도 있다.
// 앱바 레이아웃에 툴바 포함 <com.google.android.material.appbar.AppBarLayout (...생략...) android:layout_height="242dp"> </com.google.android.material.appbar.AppBarLayout>
- 앱바에 이미지를 표시할 수도 있다.
// 앱바에 이미지 표시 <com.google.android.material.appbar.AppBarLayout (...생략...) > <androidx.appcompat.widget.Toolbar (...생략...) /> <ImageView (...생략...)/> </com.google.android.material.appbar.AppBarLayout>
💡코디네이터 레이아웃 - 뷰끼리 상호 작용하기
- 코디네이터 레이아웃은 머티리얼이 아닌 제트팩의 androidx 라이브러리에서 제공하지만, 앱바 레이아웃에서 가장 많이 이용한다.
- 코디네이터 레이아웃은 뷰끼리 상호 작용해야 할 때 사용한다. 예를 들어 뷰가 스크롤되는 상황에서 위아래로 배치된 뷰가 있다고 하자.
- 해당 뷰 2개를 코디네이터 레이아웃에 넣으면 뷰에서 발생한 스크롤 정보를 코디네이터 레이아웃이 받아서 다른 뷰에 전달해 준다.
- 코디네이터 레이아웃으로 감싼 모든 자식 뷰끼리 상호작용을 하지는 않는데,
비헤이비어
를 통해 정보를 전달하고 받을 수 있다.
- 그런데 코디네이터 레이아웃을 이용하더라도 텍스트 뷰, 이미지 뷰 등은 스크롤을 연동할 수 없다. 이런 뷰에서 발생하는 스크롤을 연동하려면
androidx.core.widget.NestedScrollView
를 이용한다. app:layout_behavior
속성은 자신의 스크롤 정보를 어느 비헤이비어 클래스가 받아서 처리해야 하는지를 의미한다. 이 설정으로 코디네이터 레이아웃이 중첩 스크롤 뷰 정보를 앱바 레이아웃의ScrollingViewBehavior
클래스에 전달한다.
// 중첩 스크롤 뷰 <androidx.coordinator.layout.widget.CoordinatorLayout ...생략...> <com.google.android.material.appbar.AppBarLayout ...생략...> <androidx.appcompat.widget.Toolbar ...생략... app:layout_scrollFlags="scroll|enterAlways"/> <ImageView ...생략... app:layout_scrollFlags="scroll|enterAlways"/> </com.google.android.material.appbar.AppBarLayout> <androidx.core.widget.NestedScrollView ...생략... app:layout_behavior="@string/appbar_scrolling_view_behavior"> <TextView ...생략.../> </androidx.core.widget.NestedScrollView> </androidx.coordinator.layout.widget.CoordinatorLayout>
💡컬랩싱 툴바 레이아웃 - 앱바 접히는 형태 설정하기
컬랩싱 툴바 레이아웃
은 앱바 레이아웃 하위에 선언하여 앱바가 접힐 때 다양한 설정을 할 수 있는 뷰다. 예를 들어 앱바가 접힐 때 표시할 제목이나 색상 등을 지정할 수 있다.- 보통 앱바 레이아웃 하위에
CollapsingToolbarLayout
을 추가하여 앱바가 스크롤되어 접히거나 나타날 때 어떻게 동작해야 하는지를 설정한다.
// 컬렙싱 툴바 레이아웃 등록 <androidx.coordinatorlayout.widget.CoordinatorLayout ...생략...> <com.google.android.material.appbar.AppBarLayout ...생략...> <com.google.android.material.appbar.CollapsingToolbarLayout ...생략... app:contentScrim="?attr/colorPrimary" app:expendedTitleMarginBottom="50dp" app:expandedTitleMarginStart="48dp" app:layout_scrollFlags="scroll|exitUntilCollapsed" app:title="Appbar Title"> <ImageView ...생략... app:layout_collapseMode="parallax"/> <androidx.appcompat.widget.Toolbar ...생략... app:layout_collapseMode="pin"/> </com.google.android.material.appbar.CollapsingToolbarLayout> </com.google.android.material.appbar.AppBarLayout> <androidx.recyclerview.widget.RecyclerView ...생략... app:layout_behavior="@string/appbar_scrolling_view_behavior"/> </androidx.coordinator.layout.widget.CoordinatorLayout>
컬랩싱 툴바 레이아웃
에서 가장 중요한 속성은 앱바가 스크롤될지를 설정하는layout_scrollFlags
다. 스크롤돼야 한다면scroll
값을 지정하고|
연산자를 추가해 스크롤 시 어떻게 움직여야 하는지를 설정한다.scroll | enterAlways
: 스크롤 시 완전히 사라졌다가 거꾸로 스크롤 시 처음부터 다시 나타난다.scroll | enterAlwaysCollapsed
: 스크롤 시 완전히 사라졌다가 거꾸로 스크롤 시 처음부터 나타나지 않고 메인 콘텐츠 부분이 끝까지 스크롤된 다음에 나타난다.scroll | exitUntilCollapsed
: 스크롤 시 모두 사라지지 않고 툴바를 출력할 정도의 한 줄만 남을 때까지 스크롤된다.
- 앱바 전체의 스크롤 설정은
layout_scrollFlags
속성으로 하고, 그 하위 뷰마다 스크롤 설정은layout_collapseMode
속성으로 한다. layout_collapseMode
속성을 이용해 개별 뷰의 스크롤을 설정할 수 있다.layout_collapseMode
의 속성은 다음과 같다.pin
: 고정되어 스크롤되지 않습니다.parallax
: 함께 스크롤된다.
// 개별 뷰의 스크롤 설정 <com.google.android.material.appbar.CollapsingToolbarLayout ...생략... app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView ...생략... app:layout_collapseMode="parallax"/> <androidx.appcompat.widget.Toolbar ...생략... app:layout_collapseMode="pin"/> </com.google.android.material.appbar.CollapsingToolbarLayout>
🌼탭 레이아웃 - 탭 버튼 구성
💡탭 레이아웃
- 탭 레이아웃은 탭으로 구분하는 화면에서 탭 버튼을 배치하는 레이아웃이다.
- 탭이 많으면 스크롤되게 제공해야 한다. 또는 탭을 왼쪽으로 정렬하거나 가로 등분으로 배치할 수도 있다. 이처럼 탭 버튼을 어떻게 출력할지를 탭 레이아웃을 통해 설정할 수 있다.
// 탭 레이아웃 등록 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical"> <com.google.android.material.tabs.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content"/> <FrameLayout android:id="@+id/tabContent" android:layout_width="match_parent" android:layout_height="wrap_content"/> </LinearLayout> // 코드에서 탭 버튼 정의 binding.tabs.run{ val tab1: TabLayout.Tab = newTab() tab1.text="Tab1" addTab(tab1) val tab1: TabLayout.Tab = newTab() tab1.text="Tab2" addTab(tab2) val tab1: TabLayout.Tab = newTab() tab1.text="Tab3" addTab(tab3) }
- 탭 레이아웃의 탭 버튼을 동적으로 만들 필요가 없다면 탭 버튼을 코드에서 정의하지 않고 레이아웃 XML 파일의
TabItem
으로 정의해도 된다.
// XML 파일에서 탭 버튼 정의 <com.google.android.material.tabs.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content"> <com.google.android.material.tabs.TabItem android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Tab1"/> <com.google.android.material.tabs.TabItem android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Tab2"/> <com.google.android.material.tabs.TabItem android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Tab3"/> </com.google.android.material.tabs.TabLayout>
- 사용자가 탭 버튼을 선택할 때 출력해야 하는 내용은 코드에서 탭 버튼의 이벤트 핸들러에 명시해야 한다.
// 탭 버튼 이벤트 처리 binding.tabs.addOnTabSelectedListener(object: TabLayout.OnTabSelectedListener{ // 탭 버튼을 선택할 때 이벤트 override fun onTabSelected(tab: TabLayout.Tab?){ val transaction = supportFragmentManager.beginTransaction() when(tab?.text){ "Tab1"-> transaction.replace(R.id.tabContent, OneFragment()) "Tab2"-> transaction.replace(R.id.tabContent, TwoFragment()) "Tab3"-> transaction.replace(R.id.tabContent, ThreeFragment()) } transaction.commit() } // 선택된 탭 버튼을 다시 선택할 때 이벤트 override fun onTabReselected(tab: TabLayout.Tab?){ } // 다른 탭 버튼을 눌러 선택된 탭 버튼이 해제될 때 이벤트 override fun onTabUnselected(tab: TabLayout.Tab?){ } })
tabGravity
는 탭 버튼을 정렬하는 속성이다.- 기본값은
fill
이며 탭 버튼을 가로로 등분하여 배치한다. center
는 탭 버튼을 가운데 정렬한다.
tabMode
속성은 탭 버튼을 스크롤할 수 있는지를 설정한다.- 기본값은
fixed
인데 스크롤을 지원하지 않는다. - 만약
scrollable
로 설정하면 탭 버튼이 왼쪽부터 나열되고 모두 출력할 수 없다면 자동으로 가로 스크롤이 생긴다.
TabHost는 플랫폼 API에서 레벨 1부터 제공하는 뷰로써 과거에는 탭 화면을 만들 때 사용했다. 하지만 API 레벨 30버전에서 deprecared되었으므로 TabLayout을 사용하는 것이 좋다.
- 탭 레이아웃으로 탭 화면을 만들면서 뷰페이저와 연동할 수 있다. 예를 들어 탭 버튼을 눌러 화면을 전환할 수도 있지만, 탭 버튼 아레 콘텐츠 부분을 뷰 페이저로 제공하여 스와이프로 화면을 전환하게 할 수도 있다.
// 탭 레이아웃과 뷰 페이저 등록 <LinearLayout 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" android:orientation="vertical"> <com.google.android.material.tabs.TabLayout android:id="@+id/tabs" android:layout_width="match_parent" android:layout_height="wrap_content" app:tabMode="scrollable"> </com.google.android.material.tabs.TabLayout> <androidx.viewPager2.widget.ViewPager2 android:id="@+id/viewpager" android:layout_width="match_parent" android:layout_height="match_parent"/> </LinearLayout>
- 레이아웃 XML 파일에
TabLayout
과ViewPager2
를 등록한 후 코드에서TabLayoutMediator
를 이용해 둘을 연동하면 된다.
// 탭 레이아웃과 뷰 페이저 연동 TableLayoutMediator(tabLayout, viewPager){ tab, position -> tab.text = "Tab${(position+1)}" }.attach()
🌼네비게이션 뷰 - 드로어 화면 구성
💡네비게이션 뷰
- 네비게이션 뷰는 드로어 레이아웃으로 열린 화면에 출력되는 내용을 구성할 때 사용하는데, 보통은 메뉴 항목을 나열하는 형태로 구성한다.
- 네비게이션 뷰로 화면을 구성하려면 위쪽에 적용할 레이아웃 XML과 아래쪽에 적용할 메뉴 XML을 만든다. 그런 다음
NavigationView
의 속성으로 XML 파일을 알려 주기만 하면 된다.
// 네비게이션 뷰 등록 <androidx.drawerlayout.widget.DrawerLayout ...생략...> <LinearLayout ...생략...> (...생략...) </LinearLayout> <com.google.android.material.navigation.NavigationView android:id="@+id/main_drawer_view" android:layout_width="wrap_content" android:layout_height="match_parent" android:layout_gravity="start" app:headerLayout="@layout/navigation_header" app:menu="@menu/menu_navigation" /> </androidx.drawerlayout.widget.DrawerLayout
- 항목 선택 이벤트는 DrawerLayout의 setNavagationItemSelectedListener() 함수로 이벤트 핸들러를 지정하여 처리한다.
// 항목 선택 이벤트 핸들러 binding.mainDrawerView.serNavigationItemSelectedListener{ Log.d("kkang","navigation item click...${it.title}") true }
🌼확장된 플로팅 액션 버튼
💡확장된 플로팅 액션 버튼
- 확장된 플로팅 액션 버튼은 화면에 떠 있는 듯한 버튼을 제공하는 뷰다.
// 확장된 플로팅 액션 버튼 <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton (...생략...) android:text="extended FAB" app:icon="@android:drawable/ic_input_add"/>
- 코드에서 문자열까지 나오게 확장하거나 아이콘만 나오게 축소하는 등 버튼의 출력 형태를 조절할 수 있다.
// 확장된 플로팅 액션 버튼 조절 binding.extendedFab.setOnClickListener{ when(binding.extendedFab.isExtended){ // 아이콘과 문자열 함께 표시했다면 true->binding.extendedFab.shrink() // 아이콘만 표시 false->binding.extendedFab.extend() } }
🏁결론
안드로이드 앱 프로그래밍에서 코틀린을 사용하여 머티리얼 디자인 라이브러리, 앱바, 코디네이터 레이아웃, 컬랩싱 툴바 레이아웃, 탭 레이아웃, 네비게이션 뷰, 확장된 플로팅 액션 버튼을 구현하는 방법을 설명한다. 각 섹션에서는 해당 컴포넌트의 설정 방법과 코드 예제를 제공하며, 상호작용 및 이벤트 처리 방법도 다룬다.
Share article