새 프로젝트를 만들 때 Nagivation Drawer Activity를 선택할 수 있다
/app/manifests/AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.a36_navigationdrawer">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.A36_NavigationDrawer">
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/Theme.A36_NavigationDrawer.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
activity 태그 안에 theme 속성이 설정되어 있다. 기본으로 제공되는 테마가 아니라 직접 만든 테마를 설정하기 위한 것이다
/app/res/values/themes 폴더 안에 themes.xml 파일이다
기본 제공 테마가 아니라 상단의 액션바가 없는 스타일로 설정된다
<style name="Theme.A36_NavigationDrawer.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
activity_main.xml에서 AppBarLayout 태그로 화면 상단에 액션바를 보여줄 수 있다
activity_main에서 직접 하지않고 app_bar_main.xml 파일로 분리되어있다
<include
android:id="@+id/app_bar_main"
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />
NavigationView가 바로가기 메뉴를 위한 뷰이다
축소 아이콘을 눌렀을 때만 보이게 하기 위해서 최상위 레이아웃은 DrawerLayout으로 되어있다
<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"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
activity_main.xml에 통합하고, FloatingActionButton 제거
<?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:id="@+id/drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<androidx.coordinatorlayout.widget.CoordinatorLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/Theme.A36_NavigationDrawer.AppBarOverlay">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:popupTheme="@style/Theme.A36_NavigationDrawer.PopupOverlay" />
</com.google.android.material.appbar.AppBarLayout>
<FrameLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"></FrameLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
<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"
android:fitsSystemWindows="true"
app:headerLayout="@layout/nav_header_main"
app:menu="@menu/activity_main_drawer" />
</androidx.drawerlayout.widget.DrawerLayout>
FrameLayout의 속성으로 app:layout_behavior 속성이 부여되었는데, CoordinatorLayout 안에서 해당 레이아웃이 스크롤 등의 작업이 진행 될 때 차지할 면적을 자동으로 계산하도록 한다
NavigationView 객체에는 headerLayout 속성과 menu 속성이 있다
headerLayout은 바로가기 메뉴의 상단에 표시되면서 사용자 프로필 등을 보여줄 수 있도록 하고
menu 속성은 그 아래에 메뉴를 보여줄 수 있도록 한다
이전의 fragment1.xml, fragment2.xml, fragment3.xml과 Fragment1, Fragment2, Fragment3 자바 파일을 복사해온다
FragmentCallback.java
package com.example.a36_navigationdrawer;
import android.os.Bundle;
public interface FragmentCallback {
public void onFragmentSelected(int position, Bundle bundle);
}
MainAcitivity
package com.example.a36_navigationdrawer;
import android.os.Bundle;
import android.view.MenuItem;
import android.view.View;
import android.view.Menu;
import android.widget.Toast;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.material.navigation.NavigationView;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.widget.Toolbar;
import androidx.core.view.GravityCompat;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentHostCallback;
import androidx.navigation.NavController;
import androidx.navigation.Navigation;
import androidx.navigation.ui.AppBarConfiguration;
import androidx.navigation.ui.NavigationUI;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.appcompat.app.AppCompatActivity;
import com.example.a36_navigationdrawer.databinding.ActivityMainBinding;
import org.jetbrains.annotations.NotNull;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, FragmentCallback {
Fragment1 fragment1;
Fragment2 fragment2;
Fragment3 fragment3;
DrawerLayout drawer;
Toolbar toolbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
toolbar = findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
drawer = findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.addDrawerListener(toggle);
toggle.syncState();
NavigationView navigationView = findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener((NavigationView.OnNavigationItemSelectedListener) this);
fragment1 = new Fragment1();
fragment2 = new Fragment2();
fragment3 = new Fragment3();
getSupportFragmentManager().beginTransaction().add(R.id.container, fragment1).commit();
}
// 시스템 [BACK] 키를 눌렀을 때 호출되는 메소드
@Override
public void onBackPressed() {
if (drawer.isDrawerOpen(GravityCompat.START)) {
// 바로가기 메뉴가 열려있을 때 닫음
drawer.closeDrawer(GravityCompat.START);
} else {
super.onBackPressed();
}
}
@Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
// /app/res/menu/activity_main_drawer.xml
if (id == R.id.nav_home) {
Toast.makeText(this, "첫 번째 메뉴", Toast.LENGTH_SHORT).show();
onFragmentSelected(0, null);
} else if (id == R.id.nav_gallery) {
Toast.makeText(this, "두 번째 메뉴", Toast.LENGTH_SHORT).show();
onFragmentSelected(1, null);
} else if (id == R.id.nav_slideshow) {
Toast.makeText(this, "세 번째 메뉴", Toast.LENGTH_SHORT).show();
onFragmentSelected(2, null);
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
@Override
public void onFragmentSelected(int position, Bundle bundle) {
Fragment currentFragment = null;
if (position == 0) {
currentFragment = fragment1;
toolbar.setTitle("첫 번째 화면");
} else if (position == 1) {
currentFragment = fragment2;
toolbar.setTitle("두 번째 화면");
} else if (position == 2) {
currentFragment = fragment3;
toolbar.setTitle("세 번째 화면");
}
getSupportFragmentManager().beginTransaction().replace(R.id.container, currentFragment).commit();
}
}