건프의 소소한 개발이야기

[안드로이드] Android NavigationView 다뤄보기 본문

개발 이야기/안드로이드 이야기

[안드로이드] Android NavigationView 다뤄보기

건강한프로그래머 2016. 4. 18. 18:03

안녕하세요, 건프입니다.


이번에는 구글이 강력하게 밀고 있는 어플리케이션 디자인 패턴중 하나인 DrawerLayout 안에 있는 NavigationView 의 형태를 한번 살펴보겠습니다.


예전에는 해당기능을 이용하기 위해서 우리가 직접 모든 코드를 입력해줘야 했지만

안드로이드 스튜디오(Android Studio)가 2.0 버전 이상 올라가면서, NavigationView 를 포함하는 형태를 자동완성 시켜줍니다

(참 좋은시대)


그러니 자동완성된 형태에서 역으로 어떤식으로 구성되어 있는지 확인해보죠


우선



Navigation Drawer Activity 로 프로젝트를 생성해줍니다.


그러면 생성되는 MainActivity 의 코드중 onCreate 함수 내부는 다음과 같이 완성되어 있습니다.


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);

FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});

DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(
this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);
drawer.setDrawerListener(toggle);
toggle.syncState();

NavigationView navigationView = (NavigationView) findViewById(R.id.nav_view);
navigationView.setNavigationItemSelectedListener(this);
}


코드를 확인해보면 크게 5가지 객체를 다루고 있네요.

1) Toolbar 객체 :   나중에 ToolBar를 애니메이션을 적용시켜서 좀 더 부드러운 어플리케이션을 만들 수 있습니다

2) FloatingActionButton 객체 : 우하단에 위치하고 있는 버튼, FloatingActionButton 에 관한 것

3) DrawerLayout 객체 : Drawer 기능을 이용하기 위해서 밑에 까는 레이아웃 

4) ActionBarDrawerToggle 객체 : ActionBar 에서 좌상단에 위치한 버튼인데, NavigationView를 부를때와 안부를때 모양이 바뀌는 것을 하는 듯

5) NavigationView 객체 : 왼쪽에서 드래그해서 볼 수 있는 전광 View


우선 setContentView의 레이아웃을 그대로 따라가보면 다음과 같습니다.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.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">

<include
layout="@layout/app_bar_main"
android:layout_width="match_parent"
android:layout_height="match_parent" />

<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>

기본 바탕 레이아웃은 android.support.v4.widget 안의 DrawerLayout 입니다.

이 레이아웃은 앞의 객체 3번에서 참조되고 있어요.


그리고 주목해야 하는건 android.support.design.widget 출신의 NavigationView가 여기에 위치한다는 것입니다.

is는 앞의 객체 5번에서 참조되고 있고,


위와 같이 나오기 위해서,

가장 위에 있는 헤드레이아웃은 app:headerLayout 으로 정의된 레이아웃이고

그 아래의 매뉴레이아웃은 app:menu 로 정의된 레이아웃입니다


그럼 app:headerLayout으로 정의되어 있는 파일로 따라가보면

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
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:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:theme="@style/ThemeOverlay.AppCompat.Dark">

<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:src="@android:drawable/sym_def_app_icon" />

<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="@dimen/nav_header_vertical_spacing"
android:text="Android Studio"
android:textAppearance="@style/TextAppearance.AppCompat.Body1" />

<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="android.studio@android.com" />

</LinearLayout>

간단하게 LinearLayout 아래, ImageView 와 TextView로 이루어져 있습니다. 크기와 내용물은 각자의 취향에 알맞게 조정하시면 될 듯 합니다. 


그럼 app:menu 를 따라 들어가보면 다음과 같습니다.

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

<group android:checkableBehavior="single">
<item
android:id="@+id/nav_camera"
android:icon="@drawable/ic_menu_camera"
android:title="Import" />
<item
android:id="@+id/nav_gallery"
android:icon="@drawable/ic_menu_gallery"
android:title="Gallery" />
<item
android:id="@+id/nav_slideshow"
android:icon="@drawable/ic_menu_slideshow"
android:title="Slideshow" />
<item
android:id="@+id/nav_manage"
android:icon="@drawable/ic_menu_manage"
android:title="Tools" />
</group>

<item android:title="Communicate"
>
<menu>
<item
android:id="@+id/nav_share"
android:icon="@drawable/ic_menu_share"
android:title="Share" />
<item
android:id="@+id/nav_send"
android:icon="@drawable/ic_menu_send"
android:title="Send" />
</menu>
</item>

</menu>

menu 라는 태그안에 

group 으로 묶인 item들도 있고, 밖에 있는 item 도 있습니다. 이 차이가 위 스크린샷에서 가름선(border line)을 만든 차이일 것입니다.

굳이 group 밖에 있는 item 내에 menu 태그가 들어간것은, 이렇게도 중복되게 작성하는 것도 가능함을 보여주기 위함인 듯 합니다.

group 태그의 clickableBehavior가 single로 되어 있기 때문에 실제로 하나만 클릭할 수 있도록 하고,

클릭하고 난뒤에 다시 열어보면, 해당 item이 선택되어 있음(selected state)로 보이게 됩니다.


그러면 NavigationView에서 아이템을 선택했을때, 내부에 있는 fragment를 다루기 위해서 봐야할 부분이 있습니다.


public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener


MainActivity 를 보게되면 NavigationView.OnNavigationItemSelectedListener 를 implements 받습니다.

따라서 여기 리스너에서 작업을 하면 된다는 것을 알 수 있어요.

해당코드를 찾아가보면

@SuppressWarnings("StatementWithEmptyBody")
@Override
public boolean onNavigationItemSelected(MenuItem item) {
// Handle navigation view item clicks here.
int id = item.getItemId();

if (id == R.id.nav_camera) {
// Handle the camera action
} else if (id == R.id.nav_gallery) {

} else if (id == R.id.nav_slideshow) {

} else if (id == R.id.nav_manage) {

} else if (id == R.id.nav_share) {

} else if (id == R.id.nav_send) {

}

DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}

이렇게 이루어져 있습니다. 

따라서 선택되는 아이템이 달라짐에 따라 해당되는 fragment를 여기서 작업해서 create하면 될 것이라는 것을 알수 있네요!



이렇게 NavigationView 의 구조를 한번 들여다 보았습니다.


이제 프로젝트를 시작할 때이군요 :)

Comments