Projects/It's My Waye

[It's My Waye] 7. 메인화면 UI 구현 (DrawerLayout)

DevJaewoo 2022. 1. 23. 04:43
반응형

Intro

이전 시간에 DB 구현과 테스트를 모두 끝냈다.

이제 메인화면 부터 UI를 구현해야 한다.

 

UI는 아래와 같이 만들 예정이다.

메인화면 UI 디자인
메인화면 UI

 

찾아보니 내가 만들려고 하는 UI가 DrawerLayout이란 것을 알게 되었다.

 

마침 Android Studio에서 기본 템플릿으로 제공하는 예제 Activity가 있어서 참고용으로 예제 소스를 뜯어봤는데, 너무 복잡하게 돼있어서 그냥 인터넷 찾아보면서 만들었다.

 

프로젝트 생성
Navigation Drawer Activity 예제


DrawerLayout 구현

DrawerLayout 디자인
DrawerLayout 구조

DrawerLayout은 위와 같이 구성되어있다.

MainActivity에 content가 들어가고, 그 content 상단에 toolbar를 넣어준다.

그리고 NavigationView에 header와 main을 포함시킨다.

 

따라서 toolbar - content - nav_header - nav_main - nav 순서로 구현해볼 것이다.


layout/toolbar.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.appcompat.widget.Toolbar xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    android:elevation="4dp"
    android:background="@color/purple_500"
    app:contentInsetStart="4dp">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_gravity="start">

        <ImageButton
            android:id="@+id/ib_toolbar"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:minWidth="48dp"
            android:minHeight="48dp"
            android:layout_gravity="center_vertical"
            android:layout_marginEnd="10dp"
            android:background="#00FFFFFF"
            android:contentDescription="@string/menu_button"
            android:src="@drawable/ic_baseline_menu_24"
            app:tint="@color/white" />

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:text="@string/app_name"
            android:textColor="@color/white"
            android:textSize="25sp"
            android:textStyle="bold" />

    </LinearLayout>

</androidx.appcompat.widget.Toolbar>

 

앱의 Title과 메뉴 버튼이 들어갈 항상 상단에 고정되어있는 툴바이다.

위의 코드를 적용시키면 이런 UI가 나온다.

 

툴바


layout/content_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    xmlns:tools="http://schemas.android.com/tools"
    tools:showIn="@layout/activity_main"
    android:orientation="vertical">

    <include
        layout="@layout/toolbar"
        android:id="@+id/toolbar"/>

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/fragment_container_view"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1"/>

</LinearLayout>

 

앱의 Title과 FragmentContainerView를 포함하는 main view이다.

나중에 Navigation에서 Alarm/Noti/Settings를 선택할 시 FragmentContainerView에 들어가는 Fragment를 교체해주며 페이지를 전환시킬 것이다.


layout/nav_header_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="150dp"
    android:background="#ABCDEF">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="HEADER"
        android:textSize="40sp"/>

</LinearLayout>

 

Nav 메뉴의 header 부분이다.

나중에 사진을 넣든 아이콘을 넣든 꾸미면 된다.


menu/main_menu.xml

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/menu_alarm"
            android:title="@string/menu_alarm"
            android:icon="@drawable/ic_baseline_access_alarm_24"
            android:checkable="true"
            android:checked="true"/>

        <item
            android:id="@+id/menu_notification"
            android:title="@string/menu_notification"
            android:icon="@drawable/ic_baseline_notifications_active_24"
            android:checkable="true"
            android:checked="false"/>

        <item
            android:id="@+id/menu_settings"
            android:title="@string/menu_settings"
            android:icon="@drawable/ic_baseline_settings_24"
            android:checkable="true"
            android:checked="false"/>
    </group>
</menu>

 

Navigation에 나올 메뉴 항목들을 정의하는 곳이다.

반드시 menu 안에 group 안에 item들로 구성해야 한다.

 

난 Navigation을 화면 전환용으로 쓸 것이기 때문에 group의 checkableBehavior을 single로 해줬다. (한번에 여러 화면을 볼 일이 없으니)

 

또한 나중에 메뉴를 선택하기 위해 item의 checkable을 true로 해줘야 한다.

 

적용시키면 미리보기 창에 아래처럼 이상하게 뜨지만, 나중에 제대로 적용될 것이니 별로 신경쓰지 않아도 된다.

 

Navigation Item


layout/activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.drawerlayout.widget.DrawerLayout 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">

    <include
        android:id="@+id/content_main"
        layout="@layout/content_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <com.google.android.material.navigation.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/nav_header_main"
        app:menu="@menu/main_menu"/>

</androidx.drawerlayout.widget.DrawerLayout>

 

이제 여태 만든 컴포넌트들을 조립하는 일만 남았다.

 

우선 layout을 DrawerLayout으로 변경해주고, content_main을 include 해준다.

사실 content_main을 따로 만들지 않고 include 자리에 붙여넣기 해도 되지만, 이 방법이 뭔가 정리되어있다는 느낌이 들어서 사용했다.

 

그 다음 NavigationView를 정의하고, headerLayout에 @layout/nav_header_main을, menu에 @menu/main_menu를 넣어준다.

 

NavigationView의 layout_gravity를 start로 하면 왼쪽에서 나오고, end로 하면 오른쪽에서 나온다.

 

이때 NavigationView가 content_main보다 아래에 있어야 한다.

순서가 반대로 되어있으면 Nav의 메뉴를 선택해도 선택이 감지가 되지 않는다.

 

적용시키면 미리보기 창이 아래와 같이 뜬다.

왼쪽에 점선으로 되어있는 사각형이 NavigationView다.

Nav 디자인 미리보기


화면 구성은 다 끝났다.

이제 Kotlin 파일에서 버튼 눌렀을 때의 동작을 처리해주면 된다.

 

MainActivity.kt

class MainActivity : AppCompatActivity(), NavigationView.OnNavigationItemSelectedListener {

    private lateinit var binding: ActivityMainBinding

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        binding = ActivityMainBinding.inflate(layoutInflater)
        setContentView(binding.root)

        binding.contentMain.toolbar.ibToolbar.setOnClickListener {
            toggleDrawerLayout(binding.root)
        }

        binding.navView.setNavigationItemSelectedListener(this)
    }

    override fun onNavigationItemSelected(item: MenuItem): Boolean {
        Log.d(TAG, "onNavigationItemSelected: ${item.title}")
        return true
    }

    private fun toggleDrawerLayout(drawerLayout: DrawerLayout) {

        if(!drawerLayout.isDrawerOpen(GravityCompat.START)) {
            drawerLayout.openDrawer(GravityCompat.START)
        }
        else {
            drawerLayout.closeDrawer(GravityCompat.START)
        }
    }
}

 

Toolbar의 메뉴 버튼이 클릭됐을 때 toggleDrawerLayout 함수를 실행시켜 메뉴가 들락날락 하게 만들었다.

또 navView의 itemSelectedListener를 두어 항목이 선택되면 어떤 항목이 선택되었는지 표시되게 했다.

 

ActivityMainBinding 클래스가 없다고 나오면 아래의 코드를 build.gradle에 추가하면 된다.

binding 관련해서 따로 포스팅 할 예정이다.

 

buildFeatures {
    viewBinding true
}

동작 테스트

동작 테스트 gif

 

아주 잘 된다.

반응형