사진 1
Navigation Drawer(네비게이션 드로워)
안드로이드가 발전하고 있는 만큼 화면의 효율적인 활용이 중요시 되고 있다. ActionBar, Fragment 등을 이용하여 화면을 분할하고 각각에 역할을 줄 수 있게 되었다. Navigation Drawer도 화면을 효율적으로 사용할 수 있게 해주는 방법 중 하나이다. 대부분의 구글 앱에는 Navigation Drawer가 적용되어 있고, 인기 앱에도 자주 사용되고 있다.
소스 다운로드 및 소개 페이지
http://developer.android.com/intl/ko/training/implementing-navigation/nav-drawer.html 에서
오른쪽 중간 부분에 'Download the sample app'을 다운하면 된다.
또는
NavigationDrawer.zip
소스를 보면 메인 클래스 하나가 전부이다.
변수 정의
private DrawerLayout mDrawerLayout; // 주 기능
private ListView mDrawerList; // 내용
private ActionBarDrawerToggle mDrawerToggle; // 주 기능
private CharSequence mDrawerTitle; // ActionBar의 제목을 변경하기 위한 변수
private CharSequence mTitle; // ActionBar의 제목을 변경하기 위한 변수
private String[] mPlanetTitles; // 태양계 행성 이름들
onCreate()
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 액션바 제목
mTitle = mDrawerTitle = getTitle();
// strings.xml의 데이터 삽입
mPlanetTitles = getResources().getStringArray(R.array.planets_array);
// DrawerLayout 정의
mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
// DrawerLayout Shadow 정의(사진 2 참조)
mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
// ListView 정의
mDrawerList = (ListView) findViewById(R.id.left_drawer);
// ListView 데이터 정의
mDrawerList.setAdapter(new ArrayAdapter<String>(this,
R.layout.drawer_list_item, mPlanetTitles));
// ListView 아이템 클릭 리스너
mDrawerList.setOnItemClickListener(new DrawerItemClickListener());
// ActionBar의 홈버튼을 Navigation Drawer 토글기능으로 사용
getActionBar().setDisplayHomeAsUpEnabled(true);
getActionBar().setHomeButtonEnabled(true);
// 토글 정의
mDrawerToggle = new ActionBarDrawerToggle(
this,
mDrawerLayout,
R.drawable.ic_drawer,
R.string.drawer_open,
R.string.drawer_close
) {
public void onDrawerClosed(View view) {
getActionBar().setTitle(mTitle);
invalidateOptionsMenu();
}
public void onDrawerOpened(View drawerView) {
getActionBar().setTitle(mDrawerTitle);
invalidateOptionsMenu();
}
};
// Drawer Layout의 리스너를 mDrawerToggle로 정의
mDrawerLayout.setDrawerListener(mDrawerToggle);
// 인스턴스 상태가 존재 안하면 가장 첫번째 아이템으로 시작
if (savedInstanceState == null) {
selectItem(0);
}
}
사진 2
DrawerItemClickListener() & selectItem()
private class DrawerItemClickListener implements ListView.OnItemClickListener {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
selectItem(position);
}
}
private void selectItem(int position) {
⁄// 리스트 아이템 클릭 시 변경됨
Fragment fragment = new PlanetFragment();
// Fragment에 추가적인 정보 저장
Bundle args = new Bundle();
args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
fragment.setArguments(args);
// FragmentManger가 Fragment가 바뀔때마다 교체해줌
FragmentManager fragmentManager = getFragmentManager();
fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
// 아이템이 계속 클릭된 상태로 유지
mDrawerList.setItemChecked(position, true);
// ActionBar 제목 변경(해당 글에는 넣지 않음.)
setTitle(mPlanetTitles[position]);
// Drawer Layout 닫기
mDrawerLayout.closeDrawer(mDrawerList);
}
PlanetFragment Class
public static class PlanetFragment extends Fragment {
public static final String ARG_PLANET_NUMBER = "planet_number";
public PlanetFragment() {
// Fragment 하위 클래스 때문에 필요함
}
// 기본 Fragment의 화면 정의
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_planet, container, false);
int i = getArguments().getInt(ARG_PLANET_NUMBER);
String planet = getResources().getStringArray(R.array.planets_array)[i];
int imageId = getResources().getIdentifier(planet.toLowerCase(Locale.getDefault()),
"drawable", getActivity().getPackageName());
((ImageView) rootView.findViewById(R.id.image)).setImageResource(imageId);
getActivity().setTitle(planet);
return rootView;
}
}
이 외에도 여러 메소드들이 존재하지만 이 글에는 최소한의 Drawer Layout 생성 및 작동에 필요한 메소드들과 클래스만 적어두었다.
activity_main.xml
<android.support.v4.widget.DrawerLayout
xmlns:android="http:⁄⁄schemas.android.com⁄apk⁄res⁄android"
android:id="@+id⁄drawer_layout"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:id="@+id⁄content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent" ⁄>
<ListView
android:id="@+id⁄left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:divider="@android:color⁄transparent"
android:dividerHeight="0dp"
android:background="@android:color⁄white"⁄>
<⁄android.support.v4.widget.DrawerLayout>
DrawerLayout에 FrameLayout과 ListView를 넣어 구현하였다.
FrameLayout말고 다른 Layout이 삽입되어도 된다.
drawer_list_item.xml
<TextView xmlns:android="http:⁄⁄schemas.android.com⁄apk⁄res⁄android"
android:id="@android:id⁄text1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr⁄textAppearanceListItemSmall"
android:gravity="center_vertical"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:textColor="@android:color⁄black"
android:background="?android:attr⁄activatedBackgroundIndicator"
android:minHeight="?android:attr⁄listPreferredItemHeightSmall"⁄>
각각의 리스트 아이템에 적용되는 속성이다.
fragment_planet.xml
<ImageView xmlns:android="http:⁄⁄schemas.android.com⁄apk⁄res⁄android"
android:id="@+id⁄image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:gravity="center"
android:padding="32dp" ⁄>
각각의 Fragment의 이미지들의 대한 속성이다.
구글이 제공하는 소스에는 ListView를 이용한 Drawer Layout을 구현되어 있다. 하지만 이 ListView를 좀 더 커스텀하여 꾸밀 수도 있고, ListView가 아닌 Layout을 넣음으로써 텍스트뷰, 버튼, Radio 버튼, 체크박스, 레이아웃 종류 등 다양한 시도를 할 수 있다.
이 저작물은
크리에이티브 커먼즈 저작자표시-비영리-변경금지 4.0 국제 라이선스에 따라 이용할 수 있습니다.
RECENT COMMENT