단편 Android 개발 정리
이전 게시글: ActionBar 대신 Toolbar로 대체하기(2021년 버전)
사이드 메뉴(DrawerLayout) 구현하기 (2021년 버전)
이전 게시글에서 ActionBar를 Toolbar로 대체한 다음 햄버거 버튼까지 추가해 보았다. 본 게시글에서는 햄버거 버튼을 클릭하면 사이드 메뉴가 나타나는 것까지 구현해 보겠다. 안드로이드에서는 햄버거 버튼을 클릭했을 때 측면에서 스르륵 나타나는 사이드 메뉴를 DrawerLayout이라고 부른다. 이전 게시글의 레이아웃에서 이를 덧붙여보겠다.
이전 게시글에서 햄버거 버튼까지 반영했을 때의 레이아웃은 다음과 같다.
<?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.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
android:theme="@style/ThemeOverlay.AppCompat.ActionBar"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:menu="@menu/menu_toolbar">
</androidx.appcompat.widget.Toolbar>
</androidx.constraintlayout.widget.ConstraintLayout>
그리고 액티비티에 대한 코틀린 클래스는 다음과 같다. import
는 생략한다.
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val toolbar = findViewById<Toolbar>(R.id.toolbar)
setSupportActionBar(toolbar)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_menu)
}
override fun onCreateOptionsMenu(menu: Menu?): Boolean {
// ...
return super.onCreateOptionsMenu(menu)
}
override fun onPrepareOptionsMenu(menu: Menu?): Boolean {
// ...
return super.onPrepareOptionsMenu(menu)
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
var result = false
when (item.itemId) {
// ...
}
return result;
}
}
ConstraintLayout
을 기준으로 설명하면, 맨 위에 Toolbar
가 있고 그 아래에 붙여서 DrawerLayout
을 배치할 것이다. 그러면 레이아웃은 다음과 같이 작성할 수 있다.
<androidx.constraintlayout.widget.ConstraintLayout ...>
<androidx.appcompat.widget.Toolbar android:id="@+id/toolbar" ...>
</androidx.appcompat.widget.Toolbar>
<androidx.drawerlayout.widget.DrawerLayout
android:id="@+id/layout_drawer"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/toolbar"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="이 곳은 메인 영역이다." />
<com.google.android.material.navigation.NavigationView
android:id="@+id/navigation_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="start"
android:fitsSystemWindows="true">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="이 곳은 사이드 영역이다." />
</com.google.android.material.navigation.NavigationView>
</androidx.drawerlayout.widget.DrawerLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
TextView
는 영역 사이의 구분을 명확히 하기 위하여 임의로 넣은 요소이다. 아무튼 레이아웃을 저렇게 작성한다. DrawerLayout
내부에 사이드 메뉴가 보여질 NavigationView
가 있다는 것이다. 특히 주목할 것은 NavigationView
가 갖는 android:layout_gravity="start"
속성이다. 이 속성은 사이드 메뉴가 왼쪽에서 나타났다가 왼쪽으로 사라짐을 의미한다. 오른쪽 사이드 메뉴는 android:layout_gravity="end"
로 하면 된다.
그 다음 이전 포스트에서 햄버거 메뉴를 클릭할 때 호출되는 이벤트는 다음과 같이 처리한다. 사이드 메뉴가 이미 떠 있다면(isDrawerOpen
) 그것을 감추고(closeDrawer
), 사이드 메뉴가 감춰져 있다면 그것을 드러낸다(openDrawer
).
class MainActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
var result = false
when (item.itemId) {
android.R.id.home -> {
val layoutDrawer = findViewById<DrawerLayout>(R.id.layout_drawer)
val gravity = GravityCompat.START
if (layoutDrawer.isDrawerOpen(gravity)) {
layoutDrawer.closeDrawer(gravity)
} else {
layoutDrawer.openDrawer(gravity)
}
}
}
return result;
}
}
실행 결과는 다음과 같다.
디자인적 요소는 최대한 배제한 채, 최소한 접고 펼치는 기능적인 구현은 이것으로 끝.