16 바로가기 메뉴 만들기
바로가기 메뉴는 화면의 좌측 상단에 위치한 햄버거 모양 아이콘을 눌렀을 때 나타나는 화면을 말한다. 웹이나 앱에서 자주 사용되는 기능이며 안드로이드에서는 NavigationDrawer라는 이름으로 불린다. 바로가기 메뉴는 몇 개의 화면에서 공통으로 보여줄 수 있기 때문에 빠르게 메뉴 기능에 접근하고자 할 때 사용한다. 또한 로그인한 사용자의 프로필 정보나 설정 메뉴를 보여줄 때도 사용할 수 있다.
바로가기 메뉴를 추가하는 가장 쉬운 방법은 안드로이드에서 첫 화면의 유형으로 제공하는 것을 사용하는 것이다.
Create New Project > Navigation Drawer Activity > Next > Name 입력 > Finish
Empty Activity를 선택했을 때보다 더 많은 화면 레이아웃과 소스 파일이 포함되어 있는데, 이를 간단하게 하기 위해 통합한다. 우선 액션바는 activity_main.xml 파일에서 AppBarLayout으로 설정할 수 있으니 app_bar_main.xml 파일과 content_main.xml 파일을 통합한다.
▼ abb_bar_main.xml 파일과 content_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: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.SampleDrawer.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.SampleDrawer.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>

레이아웃 구조를 그려보았다.
abb_bar_main.xml 파일과 content_main.xml 파일의 내용을 통합했다면 이 두 개의 XML 파일은 삭제한다. activity_main_drawer.xml 안에 있는 아이템들의 id를 각각 menu1, menu2, menu3으로 변경하고, 메뉴를 선택했을 때 보일 프래그먼트 세 개를 추가한다.
-<DrawerLayout>: 평소에는 보이지 않다가 버튼을 눌렀을 때만 보이도록 해주는 레이아웃이다.
-<fitsSystemWindows>: 이 뷰를 조정해 상태 표시줄과 같은 시스템 창을 위한 공간을 확보해준다.
-<openDrawer>: 이 태그가 있다면 안드로이드 스튜디오 미리보기 창에서 NavigationView가 보인다.
-<headerLayout>: 바로가기 메뉴의 상단에 표시되면서 사용자 프로필 등을 보여줄 수 있도록 한다.
-<menu>: headerLayout 아래에 메뉴를 보여줄 수 있도록 한다.
▼ 바로가기 메뉴를 선택했을 때 프래그먼트 전환하기
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(this);
fragment1 = new Fragment1();
fragment2 = new Fragment2();
fragment3 = new Fragment3();
getSupportFragmentManager().beginTransaction().add(R.id.container, fragment1).commit();
}
@Override
public void onBackPressed() {
if(drawer.isDrawerOpen(GravityCompat.START)){
drawer.closeDrawer(GravityCompat.START);
}else{
super.onBackPressed();
}
}
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
if(id == R.id.menu1){
Toast.makeText(this, "첫 번째 메뉴 선택됨", Toast.LENGTH_LONG).show();
onFragmentSelected(0);
}else if(id == R.id.menu2){
Toast.makeText(this, "두 번째 메뉴 선택됨", Toast.LENGTH_LONG).show();
onFragmentSelected(1);
}else if(id == R.id.menu3){
Toast.makeText(this, "세 번째 메뉴 선택됨", Toast.LENGTH_LONG).show();
onFragmentSelected(2);
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
@Override
public void onFragmentSelected(int position) {
Fragment curFragment = null;
if(position == 0){
curFragment = fragment1;
toolbar.setTitle("첫 번째 화면");
}else if(position == 1){
curFragment = fragment2;
toolbar.setTitle("두 번째 화면");
}else if(position == 2){
curFragment = fragment3;
toolbar.setTitle("세 번째 화면");
}
getSupportFragmentManager().beginTransaction().replace(R.id.container, curFragment).commit();
}
}
▼ 어떤 프래그먼트를 보여줄지 선택하는 메서드를 포함하는 인터페이스 만들기
public interface FragmentCallback {
public void onFragmentSelected(int position);
}
책에는 navigationView의 리스너와 이벤트가 setNavigationItemSelectedListener, onNavigationItemSelected로 분리되어 있는데, 이걸 하나로 합칠 수도 있다. 그러면 리스너를 구현하지 않아도 되고, 메서드를 재정의하지 않아도 된다.
▼ navigationView의 리스너와 이벤트 합치기
public class MainActivity extends AppCompatActivity implements 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(new NavigationView.OnNavigationItemSelectedListener() {
@Override
public boolean onNavigationItemSelected(@NonNull MenuItem item) {
int id = item.getItemId();
if(id == R.id.menu1){
Toast.makeText(getApplicationContext(), "첫 번째 메뉴 선택됨", Toast.LENGTH_LONG).show();
onFragmentSelected(0);
}else if(id == R.id.menu2){
Toast.makeText(getApplicationContext(), "두 번째 메뉴 선택됨", Toast.LENGTH_LONG).show();
onFragmentSelected(1);
}else if(id == R.id.menu3){
Toast.makeText(getApplicationContext(), "세 번째 메뉴 선택됨", Toast.LENGTH_LONG).show();
onFragmentSelected(2);
}
drawer.closeDrawer(GravityCompat.START);
return true;
}
});
fragment1 = new Fragment1();
fragment2 = new Fragment2();
fragment3 = new Fragment3();
getSupportFragmentManager().beginTransaction().add(R.id.container, fragment1).commit();
}
@Override
public void onBackPressed() {
if(drawer.isDrawerOpen(GravityCompat.START)){
drawer.closeDrawer(GravityCompat.START);
}else{
super.onBackPressed();
}
}
@Override
public void onFragmentSelected(int position) {
Fragment curFragment = null;
if(position == 0){
curFragment = fragment1;
toolbar.setTitle("첫 번째 화면");
}else if(position == 1){
curFragment = fragment2;
toolbar.setTitle("두 번째 화면");
}else if(position == 2){
curFragment = fragment3;
toolbar.setTitle("세 번째 화면");
}
getSupportFragmentManager().beginTransaction().replace(R.id.container, curFragment).commit();
}
}

'Android' 카테고리의 다른 글
[Do it! 안드로이드 앱 프로그래밍 #17] 서비스 (0) | 2021.12.20 |
---|---|
[Do it! 안드로이드 앱 프로그래밍 #15] 뷰페이저 만들기 (0) | 2021.12.18 |
[Do it! 안드로이드 앱 프로그래밍 #14] 상단 탭과 하단 탭 만들기 (0) | 2021.12.13 |
[Do it! 안드로이드 앱 프로그래밍 #13] 액션바 사용하기 (0) | 2021.12.05 |
[Do it! 안드로이드 앱 프로그래밍 #12] 프래그먼트로 화면 만들기 (0) | 2021.12.03 |