본문 바로가기

유저 인터페이스

네비게이션 드로어 활용 - (1) 프래그먼트와 연동하기

네비게이션 드로어(Navigation drawer)는 최근 출시되는 대다수의 안드로이드 애플리케이션에서 사용하고 있는 UI 구성 요소입니다. 

이전 포스트(2013/11/05 - 네비게이션 드로어(Navigation Drawer) 사용하기)에선 네비에게이션 드로어 자체에 대한 내용을 주로 다루었는데, 이번 포스트에서는 프래그먼트와 네비게이션 드로어를 함께 사용하여 실제 애플리케이션에 적용하는 방법에 대해 알아보겠습니다.


화면에 표시할 프래그먼트 생성


예제 프로젝트에선 다음 두 프래그먼트를 네비게이션 드로어와 연결하여 사용할 것입니다.


  • TextFragment (문자열을 표시하는 프래그먼트)
  • ImageFragment (이미지를 표시하는 프래그먼트)


텍스트를 표시하는 프래그먼트인 TextFragment를 먼저 생성해 봅시다. TextFragment에서 표시할 레이아웃을 다음과 같이 작성합니다. 텍스트를 표시하는 TextView 하나를 표시하며, 표시될 텍스트는 문자열 리소스를 사용하여 별도로 저장했습니다. (@string/lorem_ipsum)


[fragment_text.xml]

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.androidhuman.example.navigationdrawer.basicfragments.app.TextFragment">

    <TextView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:text="@string/lorem_ipsum" />

</FrameLayout>


다음, TextFragment 클래스를 작성합니다. 위에서 작성한 TextFragment의 레이아웃(layout_fragment_text)을 표시하는 것 외에는 특별한 기능은 없습니다.



[TextFragment.java]

public class TextFragment extends Fragment {

    public static TextFragment newInstance() {
        TextFragment fragment = new TextFragment();
        return fragment;
    }

    public TextFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_text, container, false);
    }

}


이어서 이미지를 표시하는 프래그먼트인 ImageFragment와 그 레이아웃을 작성합니다. TextFragment와 마찬가지로 이미지(앱 아이콘)를 표시하는 기능 외에 특별한 기능은 없습니다.


[fragment_image.xml]

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.androidhuman.example.navigationdrawer.basicfragments.app.ImageFragment">

    <ImageView
        android:id="@+id/iv_fragment_image"
        android:scaleType="center"
        android:src="@drawable/ic_launcher"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</FrameLayout>



[ImageFragment.java]

public class ImageFragment extends Fragment {

    public ImageFragment newInstance(){
        ImageFragment fragment = new ImageFragment();
        return fragment;
    }


    public ImageFragment() {
        // Required empty public constructor
    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        return inflater.inflate(R.layout.fragment_image, container, false);
    }

}
메인 액티비티 구현


먼저, 다음과 같이 메인 액티비티의 레이아웃을 작성합니다. 네비게이션 드로어(DrawerLayout)가 전체를 감싸고 있고, 그 안에 메뉴를 표시하는 ListView와 프래그먼트를 표시할 공간인 FrameLayout을 지정했습니다.


[activity_main.xml]

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/dl_activity_main"
    tools:context=".MainActivity">

    <FrameLayout
        android:id="@+id/fl_activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

    <ListView android:id="@+id/lv_activity_main"
        android:background="#EDEDED"
        android:layout_width="240dp"
        android:layout_height="match_parent"
        android:layout_gravity="start" />

</android.support.v4.widget.DrawerLayout>


이제 액티비티 본체를 작성할 차례입니다. 먼저, 네비게이션 드로어 구현에 필요한 요소들과 위에서 만든 두 프래그먼트(TextFragment, ImageFragment)의 인스턴스를 선언합니다.


[MainActivity.java]

public class MainActivity extends ActionBarActivity {

    DrawerLayout dlDrawer;
    ActionBarDrawerToggle dtToggle;

    ListView lvDrawerList;
    ArrayAdapter<String> adtDrawerList;
    String[] menuItems = new String[]{"TextFragment", "ImageFragment"};

    TextFragment fragText;
    ImageFragment fragImage;



다음, onCreate() 메서드에서 각 요소들을 초기화합니다. 먼저, 두 프래그먼트를 생성한 후, 액티비티 최초 실행시 TextFragment가 표시되도록 구현하였습니다.


// Fragments
fragText = TextFragment.newInstance();
fragImage = new ImageFragment().newInstance();

getSupportFragmentManager()
        .beginTransaction()
        .replace(R.id.fl_activity_main, fragText).commit();


네비게이션 드로어에서 표시할 메뉴 항목과, 각 항목을 선택했을 때 선택한 프래그먼트를 화면에 표시합니다.


[MainAvtivity.java]

// Navigation drawer : menu lists
lvDrawerList = (ListView) findViewById(R.id.lv_activity_main);
adtDrawerList = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, menuItems);
lvDrawerList.setAdapter(adtDrawerList);
lvDrawerList.setOnItemClickListener(new AdapterView.OnItemClickListener() {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        switch(position){
            case 0:
                getSupportFragmentManager()
                        .beginTransaction()
                        .replace(R.id.fl_activity_main, fragText).commit();
                break;
            case 1:
                getSupportFragmentManager()
                        .beginTransaction()
                        .replace(R.id.fl_activity_main, fragImage).commit();
                break;
        }
        dlDrawer.closeDrawer(lvDrawerList);
    }
});


앱 아이콘 측면의 작은 아이콘을 통해 네비게이션 드로어의 동작 상태 (열림/닫힘)을 표시하기 위해, 다음과 같이 액션바 토글을 구성합니다.


[MainActivity.java]

// Navigation drawer : ActionBar Toggle
dlDrawer = (DrawerLayout) findViewById(R.id.dl_activity_main);
dtToggle = new ActionBarDrawerToggle(this, dlDrawer, R.drawable.ic_drawer, R.string.app_name, R.string.app_name);
dlDrawer.setDrawerListener(dtToggle);

getSupportActionBar().setDisplayHomeAsUpEnabled(true);


onCreate() 메서드의 구현은 모두 끝났습니다. 이제 액션바 토글의 정상 동작을 위해 아래 메서드를 다음과 같이 구현합니다.


[MainActivity.java]

@Override
protected void onPostCreate(Bundle savedInstanceState){
    super.onPostCreate(savedInstanceState);
    dtToggle.syncState();
}

@Override
public void onConfigurationChanged(Configuration newConfig){
    super.onConfigurationChanged(newConfig);
    dtToggle.onConfigurationChanged(newConfig);
}

@Override
public boolean onOptionsItemSelected(MenuItem item){
    if(dtToggle.onOptionsItemSelected(item)){
        return true;
    }
    return super.onOptionsItemSelected(item);
}


이것으로 모든 구현이 끝났습니다. 완성된 애플리케이션을 빌드 후 실행하면 다음과 같이 네비게이션 드로어와 프래그먼트가 잘 표시되는 것을 확인할 수 있습니다.