[Do it! 안드로이드 앱 프로그래밍 #16] 바로가기 메뉴 만들기
Android

[Do it! 안드로이드 앱 프로그래밍 #16] 바로가기 메뉴 만들기

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();
    }
}

바로가기 메뉴 만들기
바로가기 메뉴 만들기