NoActionBar 스타일 설정
바로가기 메뉴는 화면에 보이는 부분이므로 XML 레이아웃에서 넣어주는 것이 좋습니다.
다만 위쪽 타이틀 부분을 포함해서 화면의 전체적인 구성을 모두 넣어주어야 하므로 조금 많은 코드가 필요합니다.
하지만 한 번 익숙해지면 그대로 복사해서 사용할 수 있습니다.
액션바라 불리는 타이틀 부분이 XML 레이아웃에서 추가되므로 액티비티의 스타일은 액션바가 없는 NoActionBar로 설정해야 합니다.
AndroidManifest.xml 파일에서 액티비티에 스타일을 적용합니다.
<activity
android:name=".MainActivity"
android:label="@string/app_name"
android:theme="@style/AppTheme.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
AppTheme.NoActionBar 스타일은 /res/styles.xml 파일에 추가합니다.
<style name="AppTheme.NoActionBar">
<item name="windowActionBar">false</item>
<item name="windowNoTitle">true</item>
</style>
XML 레이아웃 정의
XML 레이아웃에서는 상단에 AppBarLayout 태그로 화면 상단에 액션바를 보여주도록 합니다.
그리고 그 아래에는 FrameLayout으로 메인 화면에 보여줄 내용을 중첩해서 넣을 수 있도록 해줍니다.
그 아래에 있는 NavigationView가 바로가기 메뉴를 위한 뷰인데 평소에는 보이지 않다가 햄버거 모양 아이콘을 눌렀을 때 보이게 됩니다.
다음은 XML 레이아웃의 기본 구조입니다. (속성은 일부 생략되어 있습니다.)
<android.support.v4.widget.DrawerLayout>
<android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayout>
<android.support.v7.widget.Toolbar />
</android.support.design.widget.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>
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.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" />
</android.support.v4.widget.DrawerLayout>
바로가기 메뉴를 위한 뷰에서는 상단에 보이는 것이 nav_header_main.xml에 들어가 있고 하단에 보이는 것이 menu 폴더 안의 activity_main_drawer에 들어가 있다는 것을 알 수 있습니다.
바로가기 메뉴 선택 시의 기능
소스 코드에서는 약간의 코드가 들어가 있는 것을 볼 수 있습니다.
그 코드를 그대로 두고 필요한 부분만 수정합니다.
바로가기 메뉴 뷰에서 메뉴가 선택되었을 때 호출되는 메소드는 다음과 같습니다.
@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
int id = item.getItemId();
if (id == R.id.nav_0) {
Toast.makeText(this, "첫번째 메뉴 선택됨.", Toast.LENGTH_LONG).show();
onFragmentSelected(0, null);
} else if (id == R.id.nav_1) {
Toast.makeText(this, "두번째 메뉴 선택됨.", Toast.LENGTH_LONG).show();
onFragmentSelected(1, null);
} else if (id == R.id.nav_2) {
Toast.makeText(this, "세번째 메뉴 선택됨.", Toast.LENGTH_LONG).show();
onFragmentSelected(2, null);
}
DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
생각해보기
- 바로가기 메뉴를 볼 수 있게 하는 햄버거 모양 아이콘을 앱의 모든 화면에 넣는 것이 좋을까요?
- 바로가기 메뉴를 보여주는 것과 옵션 메뉴를 보여주는 것과의 차이점은 무엇일까요?
참고 자료
comment
지금 주어지는 코드가 너무 달라서 두번째 영상 후반부쯤 부터는 지금 쓸 수 없는 내용이네요.ㅠㅠ
지금 아예 주어지는 코드가 달라요
현재 Navigation view의 메뉴를 하나 클릭하면 fragment가 실행되어 각각의 화면을 보여주고 있습니다. navigation view를 통한 앱 구성이 요즘 많이 있는데 이럴경우 대부분이 fragment로 구현하게 되는건가요? 아니면 액티비티를 새로 intent로 해서 실행시키는건가요?
이런 화면 구성을 fragment랑 activity 둘 중 하나 선택에 대해서 기준이 궁금합니다!
현재 버전에서는 onNavigationItemSelected 함수를 사용하지 않고 NavigationUI.setupWithNavController() 함수를 통해 자동으로 item 클릭 시 fragment가 전환되도록 구현되어 있습니다.
블로그에 정리해놨으니 궁금하신 분들은 참고하세요!
https://ju-hy.tistory.com/57
현재 버전에서는 클릭시에 대한 Toast 출력 할 시에 setNavigationItemSelectedListener를 사용하시면 자동으로
onNavigationItemSelected method가 형성되니 참고하세요!
현재는 코드가 아예 다르게 나오는데 어떻게 해야하나요
프로젝트 생성시 현재 버전에선 코드가 좀 다르게 나오더라구요
이벤트리스너 대신 navigation - mobile_navigation xml 파일에서 처리하는듯 보였습니다.
🌟생각해보기🌟
1. 상위 화면(메인 화면과 같은) 에 주로 넣고 세부 화면에서는 넣지 않는 것이 UX를 고려한 디자인이라고 생각합니다. 모든 화면에 넣게 되어 세부 화면에서도 다른 세부화면으로 이동하게 된다면 화면 Stack이 꼬이게 되어 예상대로 Pop이 되지않아 사용성을 해친다고 생각합니다.
2. 여러 메뉴를 나열하고 화면 전환과 같은 기능을 넣을 수 있다는 것은 동일하지만 디자인과 사용성 차이라고 생각합니다. 또한 바로가기 메뉴는 옵션 메뉴에서 넣을 수 없는 레이아웃을 더 추가할 수 있습니다.
실습에 필요한 profile.png 제공 부탁드립니다
생각해보기
1. 모든 화면에 넣는 것은 불필요하다고 생각합니다. 액션바에 넣으면 한 번만 넣어도 되지 않을까요 ??
2. 솔직히 차이점을 잘 모르겠습니다. 다만 옵션메뉴의 경우에는 메뉴폴더의 main.xml에 구현되어 있는 것을 볼 수 있었습니다.
네비게이션뷰를 통한 바로가기메뉴는 보통 앱 내 많은 화면에서 사용이되는데요
이 경우 어떤식으로 프로그래밍하는게 코드의 중복을 가장 줄일 수 있는 효율적인 프로그래밍이 될 수 있을지 궁금합니다.
NavigationView태그를 별도의 레이아웃으로 독립시켜 만들어 놓은 뒤,
사용하는 액티비티의 레이아웃의 최상위 레이아웃을 DrawerLayout으로 놓고 NavigationView가 정의 된 레인아웃파일을 include해서 사용하는건가요?
NavigationView를 호출하기 위해선 그 레이아웃의 최상위가 DrawerLayout로 정의되어있는 상태에서만 include해야하는건지가 첫번째로 궁금하고,
이에 대한 자바파일에서의 OnNavigationItemSelectedListener 코딩 중복을 피하기위해서 해당 인터페이스를 상속받는 클래스를 만들어 선택에 대한 기능들을 구현한 뒤 각 액티비티마다 객체화를 통해 내부에 정의 된 리스너를 OnNavigationItemSelectedListener생성 시 전달해주는 식으로 프로그래밍 하여 중복을 잡는건지 혹은 더 나은 방법이 있는건지가 두번째로 궁금합니다.
해당 네비게이션뷰 프로그래밍에 있어서 여러 액티비티에서 호출되어 사용 될 시에, 실제 개발자분들은 어떤식으로 작업하여 중복을 최소화하시는지 궁금합니다.
드디어 시험이 끝나고 다시 안드로이드를 공부할 수 있다는게 행복합니다