Archives
Recent Posts
«   2024/10   »
1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31
Today
Total
관리 메뉴

안드로이드 개발자의 창고

[42일차 Android] DrawerLayout 본문

Computer/Android

[42일차 Android] DrawerLayout

Wise-99 2023. 7. 6. 18:30

 

 

 

출처 : 안드로이드 앱스쿨 2기 윤재성 강사님 수업 PPT

 

 

 

📖 DrawerLayout

  • 좌측 상단의 네비게이션 버튼을 누르면 좌측에서 메뉴가 나타나는 UI
  • 대부분이 구현되어 있으므로 필요한 부분만 변경해서 사용한다.
  • 새로운 Activity를 추가할 때 Navigation Drawer Activity 선택한다.

 

구조

activity_main.xml

  • <include>
    • 다른 layout을 포함시키는 요소
    • 프래그먼트가 교체되는 화면 부분에 해당하며 layout/app_bar_main.xml 파일이 설정되어 있다.

 

  • nav_view(NavigationView)
    • 좌측에서 나타나는 메뉴가 나타날 수 있도록 해주는 View
    • headerLayout에는 nav_header_main.xml을, menu에는 menu/activity_main_drawer.xml을 이용하여 구성되어 있다.

 

  • nav_header_main.xml : 좌측에서 나타나는 NavigationView의 상단 부분
  • menu/activity_main_drawer.xml : NavigationView의 하단 부분, 메뉴 파일을 이용해 사용자가 선택할 화면 목록을 구성한다.

 

 

 

app_bar_main.xml

  • toolbar
    • 화면의 toolbar에 관련된 설정을 할 수 있다.
  •  <include>
    • layout/content_main.xml 파일이 설정되어 있다.
    • 이 부분에는 fragment가 존재하며 이 fragment 에 다른 Fragment 표시하여 화면을 교체하는 역할을 하게 된다.

 

 

 

content_main.xml

  • nav_host_fragment
    • 보여주고자 하는 Fragment들을 설정하는 부분
    • navGraph 속성에 보여줄 Fragment들이 등록되어 있는 xml 파일을 설정한다.

 

 

 

navigation/mobile_navigation.xml

  • Controller가 관리할 Fragment들을 등록하는 xml 파일
  • 이 파일에 Fragment를 등록할 때 설정하는 id가 매우 중요하다.
  • 좌측에서 나타나는 메뉴를 클릭했을 때 클릭한 메뉴의 id와 동일한 id가 셋팅되어 있는 fragment가 화면에 나타나게 된다.
  • 이 부분은 모두 설정되어 있기 때문에 개발자는 Fragment를 등록할 때 id를 메뉴의 id와 동일하게만 설정해주면 된다.

 

 

 

예제 코드

nav_header_main.xml

<?xml version="1.0" encoding="utf-8"?>
<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="@dimen/nav_header_height"
    android:background="@drawable/side_nav_bar"
    android:gravity="bottom"
    android:orientation="vertical"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:theme="@style/ThemeOverlay.AppCompat.Dark">

    <ImageView
        android:id="@+id/imageViewHeader"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/nav_header_desc"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        app:srcCompat="@mipmap/ic_launcher_round" />

    <TextView
        android:id="@+id/textViewHeader1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="@dimen/nav_header_vertical_spacing"
        android:text="@string/nav_header_title"
        android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

    <TextView
        android:id="@+id/textViewHeader2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/nav_header_subtitle" />
</LinearLayout>
  • 이 부분은 로그인한 사용자와 관련된 정보를 여주는 부분이다.
  • 보통 로그인한 사용자에 따라 표시되는 데이터가 다르기 때문에 코드로 처리해주는 것이 일반적이다.

 

 

 

values/strings.xml

<resources>
    ...

    <string name="first_name">First</string>
    <string name="second_name">Second</string>
    <string name="third_name">Third</string>
</resources>
  • 각 프래그먼트의 이름으로 사용할 문자열을 등록한다.

 

 

 

navigation/mobile_navigation.xml

<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/mobile_navigation"
    app:startDestination="@id/firstFragment">
    <fragment
        android:id="@+id/firstFragment"
        android:name="com.test.android64_drawlayout.ui.FirstFragment"
        android:label="@string/first_name"
        tools:layout="@layout/fragment_first" />
    <fragment
        android:id="@+id/secondFragment"
        android:name="com.test.android64_drawlayout.SecondFragment"
        android:label="@string/second_name"
        tools:layout="@layout/fragment_second" />
    <fragment
        android:id="@+id/thirdFragment"
        android:name="com.test.android64_drawlayout.ThirdFragment"
        android:label="@string/third_name"
        tools:layout="@layout/fragment_third" />
</navigation>
  • 사용할 프래그먼트들을 설정해준다.

 

 

 

menu/activity_main_drawer.xml

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

    <group android:checkableBehavior="single">
        <item
            android:id="@+id/firstFragment"
            android:icon="@android:drawable/ic_menu_compass"
            android:title="첫번째 프래그먼트" />
        <item
            android:id="@+id/secondFragment"
            android:icon="@android:drawable/ic_menu_directions"
            android:title="두번째 프래그먼트" />
        <item
            android:id="@+id/thirdFragment"
            android:icon="@android:drawable/ic_menu_delete"
            android:title="세번째 프래그먼트" />
    </group>
</menu>
  • 메뉴를 등록한다.
  • 메뉴 항목의 id는 mobile_navigation.xml에 등록한 프래그먼트들의 id와 일치해야 한다.
  • 사용자가 선택한 메뉴의 id와 동일한 id로 등록되어 있는 프래그먼트가 나타난다.

 

 

 

MainActivity.kt

class MainActivity : AppCompatActivity() {

    private lateinit var appBarConfiguration: AppBarConfiguration
    private lateinit var binding: ActivityMainBinding

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

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

        setSupportActionBar(binding.appBarMain.toolbar)

        //  Step01 ============================================
        // Header 부분의 LinearLayout을 추출한다.
        val headerLayout = binding.navView.getHeaderView(0) as LinearLayout
        // 하위의 View들을 추출한다.
        val navHeaderMainBinding = NavHeaderMainBinding.bind(headerLayout)
        navHeaderMainBinding.imageViewHeader.setImageResource(R.drawable.imgflag8)
        navHeaderMainBinding.textViewHeader1.text = "한국사람"
        navHeaderMainBinding.textViewHeader2.text = "나는 가끔 눈물을 흘린다...."

        //  Step01 ============================================

        binding.appBarMain.fab.setOnClickListener { view ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                .setAction("Action", null).show()
        }
        
        val drawerLayout: DrawerLayout = binding.drawerLayout
        val navView: NavigationView = binding.navView
        val navController = findNavController(R.id.nav_host_fragment_content_main)

        appBarConfiguration = AppBarConfiguration(
            setOf(
                R.id.firstFragment, R.id.secondFragment, R.id.thirdFragment
            ), drawerLayout
        )
        setupActionBarWithNavController(navController, appBarConfiguration)
        navView.setupWithNavController(navController)
    }

    override fun onCreateOptionsMenu(menu: Menu): Boolean {
        menuInflater.inflate(R.menu.main, menu)
        return true
    }

    override fun onSupportNavigateUp(): Boolean {
        val navController = findNavController(R.id.nav_host_fragment_content_main)
        return navController.navigateUp(appBarConfiguration) || super.onSupportNavigateUp()
    }
}
  • Step01 : nav_header_main.xml에 표시할 데이터를 설정한다.
  • appBarConfiguration = AppBarConfiguration( ... ), drawerLayout : setOf에 메뉴의 item을 순서대로 작성한다.