사진 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 국제 라이선스에 따라 이용할 수 있습니다.
by JamesY 2013. 11. 13. 19:46
| 1 |