[Android] Navigation Bar와 Bottom Sheet를 같이 쓸 때 문제점과 주의사항
프로젝트를 진행하면서 Navigation Bar 위에 Bottom Sheet를 구현해야 하는 일이 생겼다.
만드는 과정 중에 여러가지 문제점을 발견하게 되어 작성해본다.
먼저 Navigation Bar와 Bottom Sheets에 대해 자세하게 알아보자.
Navigation Bar
Navigation bars offer a persistent and convenient way to switch between primary destinations in an app.
내비게이션 바는 앱에서 기본 대상 간에 전환할 수 있는 지속적이고 편리한 방법을 제공합니다.
Navigation Bar는 콘텐츠간 편리하게 전환 할 수 있도록 AndroidX에서 제공되는 UI이다.
<com.google.android.material.bottomnavigation.BottomNavigationView
style="@style/Widget.Material3.BottomNavigationView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:menu="@menu/bottom_menu">
</com.google.android.material.bottomnavigation.BottomNavigationView>
XML에서 위 코드를 추가하고 네비게이션에 들어갈 메뉴를 추가하고 사용할 수 있다.
Bottom Sheets
Bottom sheets are surfaces containing supplementary content, anchored to the bottom of the screen.
하단 시트는 화면 하단에 고정된 보충 콘텐츠를 포함하는 표면입니다.
Bottom Sheets는 화면 하단에 콘텐츠를 띄울 수 있도록 Material에서 제공하는 컴포넌트이다.
Bottom Sheets에는 두가지 종류가 있다.
- Standard Bottom Sheets
- Modal Bottom Sheets
Standard Bottom Sheets는 오로지 해당 컨테이너만 제공해주고 특별한 기능은 없다.
Modal Bottom Sheets는 다이얼로그 프래그먼트 형태로 제공하기 때문에 더욱 다양한 콘텐츠를 담을 수 있고, 백그라운드의 어두운 효과를 주는 Scrim 색상을 지원한다.
어느게 더 좋다는 없기 때문에 상황에 따라 알맞게 사용하면 된다.
<androidx.coordinatorlayout.widget.CoordinatorLayout
...>
<FrameLayout
...
android:id="@+id/standard_bottom_sheet"
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
<!-- Bottom sheet contents. -->
</FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
Standard Bottom Sheets는 XML에서 작성만 하면 되고, CoordinatorLayout의 최상단에 위치해야하며 layout_behavior를 통해 Bottom Sheet Behavior를 지정해주면 동작한다.
class ModalBottomSheet : BottomSheetDialogFragment() {
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.modal_bottom_sheet_content, container, false)
companion object {
const val TAG = "ModalBottomSheet"
}
}
class MainActivity : AppCompatActivity() {
...
val modalBottomSheet = ModalBottomSheet()
modalBottomSheet.show(supportFragmentManager, ModalBottomSheet.TAG)
...
}
Modal Bottom Sheets를 사용하는 경우에는 프래그먼트로 이루어져있기 때문에 BottomSheetDialogFragment를 상속받는 클래스를 생성해서 Standard Bottom Sheet의 XML과 연결하면 된다.
같이 사용할 때 문제점
Navigation Bar와 Bottom Sheets를 같이 사용할 때 문제점이 생기는 것을 발견했다.
Navigation Bar는 하단에 위치하면서 아이템 목록을 클릭하면 프래그먼트 전환을 하도록 돕는다.
반면에 Bottom Sheet는 하단에 위치하면서 시트를 올리면 시트 내부 콘텐츠가 보이도록 하는 기능이다.
우리는 여기서 두 컴포넌트의 공통점을 찾을 수 있다.
둘 다 View의 하단에 위치해야 한다.
따라서 둘 다 하단에 배치하게 된다면 다음과 같이 컴포넌트가 겹치는 문제가 생긴다.
이런 문제는 elevation값을 주어 Navigation Bar를 상단으로 배치하고 Bottom Sheets의 높이를 Navigation Bar의 상단으로 오게끔 배치하면 된다.
//Bottom Sheets
<FrameLayout
android:id="@+id/bottom_sheet"
style="@style/Widget.Material3.BottomSheet"
android:layout_width="match_parent"
android:layout_height="500dp"
android:layout_marginLeft="30dp"
android:layout_marginRight="30dp"
android:background="@drawable/dialog_layout"
android:orientation="vertical"
app:behavior_hideable="false"
app:behavior_peekHeight="105dp" //peekHeight로 Bottom Sheet의 기본 높이를 설정할 수 있다.
app:layout_behavior="com.google.android.material.bottomsheet.BottomSheetBehavior">
//Navigation Bar
<com.google.android.material.bottomnavigation.BottomNavigationView
style="@style/Widget.Material3.BottomNavigationView"
android:layout_width="match_parent"
android:layout_height="80dp"
android:layout_gravity="bottom"
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:background="@drawable/bottom_menu_layout"
android:backgroundTint="@color/highSchoolFish_Main"
app:elevation="20dp" // elevation으로 Navigation의 높이를 높여 상단에 배치한다.
app:itemActiveIndicatorStyle="@color/white"
app:itemIconSize="20dp"
app:itemIconTint="@color/white"
app:itemTextColor="@color/white"
app:labelVisibilityMode="unlabeled"
app:menu="@menu/bottom_menu">
</com.google.android.material.bottomnavigation.BottomNavigationView>
이렇게 코드를 짜면 다음처럼 나오게 된다.
다른 속성들도 디자이너가 요구한 디자인을 적극 반영하기 위해 쓰여진 속성이다.
보는 것 처럼 Navigation Bar의 양쪽에 여백이 있고 그 위에 더 좁은 Bottom Sheets가 있다.
이 디자인 때문에 생기는 문제가 하나 더 있다.
바로 Modal Bottom Sheet를 사용하지 못한다.
위에서 이야기 했지만 Bottom Modal Sheet는 프래그먼트 다이얼로그 형태로 액티비티의 최상단에 뜨는 구조이고 Scrim 색상으로 백그라운드가 어두워지는 효과를 제공한다.
Modal Bottom Sheet를 사용하려는 이유는 Scrim 색상을 입히기 위함이다. (Scrim = Bottom Sheet를 제외한 백그라운드 색상)
Modal Sheets를 사용하면 Navigation 아래에 Bottom Sheets가 있는 구조가 나오지 못하고 위 사진처럼 Bottom Sheets가 맨 위에 노출된다. 디자이너가 요구한 디자인을 하기 위해서는 Standard Bottom Sheets를 사용해야 하고 결국 Scrim 색상을 지원하지 않아 위처럼 가독성이 떨어지게 된다.
같이 사용할 때 주의사항
그러면 Navigation Bar와 Bottom Sheets를 같이 사용할 때 주의해야 할 사항들을 볼것이다.
Material 디자인 가이드라인을 최대한 반영해서 작성했다.
Bottom Sheets를 풀스크린으로 제작해 가독성 유지
Bottom Sheets가 열렸을 때 화면의 일부만 차지하도록 제작하지 않고 화면 전체를 덮도록 하는 것이다.
상황에 따라 다르겠지만, 위 상황처럼 Navigation Bar가 상단에 위치해야 할 때 Modal Bottom Sheet를 사용을 못하기에 편법(?)으로 Standard Bottom Sheet를 전체 스크린을 사용하도록 만들면 된다.
Navigation Bar 또한 양쪽 여백을 없애야 자연스러운 화면이 나올 것이다.
차라리 이게 더 직관적이고 가독성 하나는 끝내준다.
Bottom Sheets를 최소화 시켜 간섭 최소화
위와 반대로 Bottom Sheets를 최소화로 만들어 액티비티와 간섭을 최소화 시키는 것이다.
Modal Bottom Sheets를 사용 못하는 상황이기에 백그라운드에 있는 액티비티도 같이 동작되고 있는 상태이다.
따라서 Bottom Sheets를 액티비티 콘텐츠와 같이 사용할 수 있도록 올라오는 높이를 최소화시키고 Bottom Sheets의 콘텐츠를 줄이는 것이다.
위보다 다소 옹졸해보이지만 적은 내용의 콘텐츠를 표시하기엔 적절하다.
결론적으로 주의할 점은 디자인 가이드라인에서 벗어나지 않는 선에서 가독성이 좋아야 하며 간섭이 없어야 한다.
Navigation Bar와 Bottom Sheets 둘 다 하단에 위치하는 컴포넌트이니 서로 디자인 가이드라인에 벗어나지 않는 선에서 적절한 조화를 이뤄야 할 것이다.
출처