Skip to content

Most visited

Recently visited

navigation

ナビゲーションドロワーの作成

ナビゲーションドロワーは、画面の左端にアプリのメイン ナビゲーション オプションを表示するパネルです。 通常は非表示ですが、ユーザーが画面の左端から指をスワイプしたり、アプリのトップレベルでユーザーがアクションバーにあるアプリのアイコンをタッチすると表示されます。

このレッスンでは、サポート ライブラリで入手可能な DrawerLayout API を使用してナビゲーションドロワーを実装する方法について説明します。

ナビゲーションドロワーの設計

アプリでナビゲーションドロワーを使用するか判断する前に、ナビゲーションドロワー設計ガイドで使用例とデザイン方針について把握するようにしてください。

ドロワー レイアウトを作成する

ナビゲーションドロワーを追加する場合、DrawerLayout オブジェクトをレイアウトのルートビューとして、ユーザー インターフェースを指定します。DrawerLayout の内部に画面のメイン コンテンツを含むビュー(ドロワーが非表示の場合の基本レイアウト)を 1 つと、ナビゲーションドロワーのコンテンツを含む別のビューを追加します。

たとえば、次のレイアウトは 2 つの子ビューを持つ DrawerLayout を使用しています。子ビューはメイン コンテンツ(実行時に Fragment で設定)を含む FrameLayoutと、ナビゲーションドロワー用の ListViewです。

<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">
    <!-- The main content view -->
    <FrameLayout
        android:id="@+id/content_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />
    <!-- The navigation drawer -->
    <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="#111"/>
</android.support.v4.widget.DrawerLayout>

このレイアウトは重要なレイアウト上の特徴をいくつか示しています。

ドロワーリストを初期化する

ナビゲーションドロワーを作成する場合、まずはドロワーのリスト項目を初期化します。 方法はアプリのコンテンツに依存しますが、ナビゲーションドロワーは通常、ListView で構成されているため、リストは AdapterArrayAdapterSimpleCursorAdapter など)を含んでいる必要があります。

たとえば、次のようにして文字列配列でナビゲーション リストを初期化します。

public class MainActivity extends Activity {
    private String[] mPlanetTitles;
    private DrawerLayout mDrawerLayout;
    private ListView mDrawerList;
    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mPlanetTitles = getResources().getStringArray(R.array.planets_array);
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerList = (ListView) findViewById(R.id.left_drawer);

        // Set the adapter for the list view
        mDrawerList.setAdapter(new ArrayAdapter<String>(this,
                R.layout.drawer_list_item, mPlanetTitles));
        // Set the list's click listener
        mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

        ...
    }
}

このコードは、ナビゲーションドロワーのリスト上のクリック イベントを受け取るために setOnItemClickListener() も呼び出します。次に、このインターフェースの実装方法と、ユーザーが項目を選択したときのコンテンツ ビューの変更方法について説明します。

ナビゲーション クリック イベントを処理する

ユーザーがドロワーのリストで項目を選択すると、システムは setOnItemClickListener() に渡される OnItemClickListeneronItemClick() を呼び出します。

onItemClick() メソッドで実行する内容は、アプリの構造をどのように実装するかによって異なります。 次の例では、リストで項目を選択するたびに、異なる Fragment をメインコンテンツ ビュー(R.id.content_frame ID で指定される FrameLayout 要素)に挿入します。

private class DrawerItemClickListener implements ListView.OnItemClickListener {
    @Override
    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        selectItem(position);
    }
}

/** Swaps fragments in the main content view */
private void selectItem(int position) {
    // Create a new fragment and specify the planet to show based on position
    Fragment fragment = new PlanetFragment();
    Bundle args = new Bundle();
    args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);
    fragment.setArguments(args);

    // Insert the fragment by replacing any existing fragment
    FragmentManager fragmentManager = getFragmentManager();
    fragmentManager.beginTransaction()
                   .replace(R.id.content_frame, fragment)
                   .commit();

    // Highlight the selected item, update the title, and close the drawer
    mDrawerList.setItemChecked(position, true);
    setTitle(mPlanetTitles[position]);
    mDrawerLayout.closeDrawer(mDrawerList);
}

@Override
public void setTitle(CharSequence title) {
    mTitle = title;
    getActionBar().setTitle(mTitle);
}

オープン イベントとクローズ イベントをリッスンする

ドロワーのオープン イベントとクローズ イベントをリッスンするには、DrawerLayoutsetDrawerListener() を呼び出し、DrawerLayout.DrawerListener の実装に引き渡します。 このインターフェースは、onDrawerOpened()onDrawerClosed() などのドロワー イベント向けにコールバックを提供します。

ただし、アクティビティにアクションバーが含まれている場合は、DrawerLayout.DrawerListener を実装せず、代わりに ActionBarDrawerToggle クラスを拡張することができます。 ActionBarDrawerToggleDrawerLayout.DrawerListener を実装し、引き続きそのコールバックをオーバーライドすることができ、アクションバー アイコンとナビゲーションドロワーの間の連携が適切に機能します(次のセクションで詳しく説明します)。

ナビゲーションドロワーの設計ガイドで説明しているように、ドロワーが表示されるときのアクションバーのコンテンツを変更する(メイン コンテンツの状況に応じてタイトルを変更し、アクション項目を削除するなど)必要があります。 次のコードは、ActionBarDrawerToggle クラスのインスタンスで DrawerLayout.DrawerListener コールバック メソッドをオーバーライドすることで、前述の処理を実行する方法を示しています。

public class MainActivity extends Activity {
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    private CharSequence mDrawerTitle;
    private CharSequence mTitle;
    ...

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...

        mTitle = mDrawerTitle = getTitle();
        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,
                R.string.drawer_open, R.string.drawer_close) {

            /** Called when a drawer has settled in a completely closed state. */
            public void onDrawerClosed(View view) {
                super.onDrawerClosed(view);
                getActionBar().setTitle(mTitle);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            }

            /** Called when a drawer has settled in a completely open state. */
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                getActionBar().setTitle(mDrawerTitle);
                invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()
            }
        };

        // Set the drawer toggle as the DrawerListener
        mDrawerLayout.setDrawerListener(mDrawerToggle);
    }

    /* Called whenever we call invalidateOptionsMenu() */
    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        // If the nav drawer is open, hide action items related to the content view
        boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
        menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);
        return super.onPrepareOptionsMenu(menu);
    }
}

次に、アクションバー アイコンによる操作を処理するために必要な ActionBarDrawerToggle コンストラクタ引数とその他のステップについて説明します。

アプリのアイコンによるオープンとクローズ

画面の左端から、または左端に向かってスワイプすると、ナビゲーションドロワーのオープンとクローズができます。アクションバーを使用している場合は、アプリのアイコンをタッチしてもナビゲーションドロワーのオープンとクローズができるようにする必要があります。 さらにアプリのアイコンは、特別なアイコンでナビゲーションドロワーの存在を示します。 前述の ActionBarDrawerToggle を使用して、このすべての動作を実装できます。

ActionBarDrawerToggle を動作させるには、次の引数を取るコンストラクタでインスタンスを作成します。

次に、ドロワー リスナーとして ActionBarDrawerToggle のサブクラスを作成しているかどうかにかかわらず、アクティビティのライフサイクルを通じて、いくつかの箇所で ActionBarDrawerToggle を呼び出す必要があります。

public class MainActivity extends Activity {
    private DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mDrawerToggle;
    ...

    public void onCreate(Bundle savedInstanceState) {
        ...

        mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        mDrawerToggle = new ActionBarDrawerToggle(
                this,                  /* host Activity */
                mDrawerLayout,         /* DrawerLayout object */
                R.string.drawer_open,  /* "open drawer" description */
                R.string.drawer_close  /* "close drawer" description */
                ) {

            /** Called when a drawer has settled in a completely closed state. */
            public void onDrawerClosed(View view) {
                super.onDrawerClosed(view);
                getActionBar().setTitle(mTitle);
            }

            /** Called when a drawer has settled in a completely open state. */
            public void onDrawerOpened(View drawerView) {
                super.onDrawerOpened(drawerView);
                getActionBar().setTitle(mDrawerTitle);
            }
        };

        // Set the drawer toggle as the DrawerListener
        mDrawerLayout.setDrawerListener(mDrawerToggle);

        getActionBar().setDisplayHomeAsUpEnabled(true);
        getActionBar().setHomeButtonEnabled(true);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState) {
        super.onPostCreate(savedInstanceState);
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();
    }

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

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Pass the event to ActionBarDrawerToggle, if it returns
        // true, then it has handled the app icon touch event
        if (mDrawerToggle.onOptionsItemSelected(item)) {
          return true;
        }
        // Handle your other action bar items...

        return super.onOptionsItemSelected(item);
    }

    ...
}

ナビゲーションドロワーの使用例は、このページの先頭で入手可能なサンプルをダウンロードして確認してください。

This site uses cookies to store your preferences for site-specific language and display options.

Get the latest Android developer news and tips that will help you find success on Google Play.

* Required Fields

Hooray!

WeChat で Google Developers をフォローする

Browse this site in ?

You requested a page in , but your language preference for this site is .

Would you like to change your language preference and browse this site in ? If you want to change your language preference later, use the language menu at the bottom of each page.

This class requires API level or higher

This doc is hidden because your selected API level for the documentation is . You can change the documentation API level with the selector above the left navigation.

For more information about specifying the API level your app requires, read Supporting Different Platform Versions.

Take a short survey?
Help us improve the Android developer experience. (Dec 2017 Android Platform & Tools Survey)