Im Zuge der Google I/O wurde auch die Support Library für Android-Apps geupdated, die nun auch den Navigation Drawer offiziell unterstützt. Dieser bietet eine Sidebar als Navigationsmöglichkeit, wie sie bereits aus anderen Apps - wie der YouTube-App - bekannt ist.

Wozu ein Navigation Drawer?

Diese Art der Navigation ist besonders für Apps mit mehreren, wichtigen Ebenen gedacht, wie es unter anderem die Facebook-App vormacht. Dort gibt es die Möglichkeit zu den Nachrichten, Gruppen und auch den aktuellen Meldungen zu gelangen. Da die Navigation bereits durch einen Wischer von der linken zur rechten Seite oder einen Druck auf den ActionBar-Titel geöffnet wird, ist sie von überall aus erreichbar.

Weitere Einsatzszenarien und Verwendungshinweise im Hinblick auf das Design liefern die Design-Guidelines von Google, die Sie hier finden können.

Beispiele

In vielen Apps ist der Navigation Drawer bereits implementiert. Im folgenden sehen Sie nun einige Beispiele dafür:
Navigation Drawer: Gmail
Navigation Drawer: feedly
Navigation Drawer: ASDV

Implementation und Programmierung

Die Implementation mit eigenem und erweitertem Design, bzw. Style ist sehr einfach und auch für Anfänger geeignet. Im folgenden werde ich Ihnen zeigen, wie einfach Sie einen Navigation Drawer mit ActionBarSherlock implementieren können und Ihnen das Beispielprojekt auch zum Download anbieten. Falls Sie kein eigenes Design wünschen, sondern nur eine Auflistung der Navigationselemente, können Sie auch die Anleitung aus dem Android Developers Training verwenden.

  • Erstellen Sie ein neues Projekt oder öffnen Sie ein bereits bestehendes Projekt.
  • Machen Sie einen Rechtsklick auf Ihr Projekt und wählen Sie Android Tools –> Add Support Library aus. Überschreiben Sie die Support Library von ActionBarSherlock dabei einfach.
  • Ändern Sie das Theme Ihrer App in ein Theme.Sherlock.# ab.
  • Öffnen Sie die Layout-Datei, in welcher Sie den Navigation Drawer nutzen wollen und ändern Sie diese einfach folgendermaßen ab:

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

	<!-- Ihre Layout-Elemente oder ein Fragment-Container -->

	<ListView
		android:id="@+id/left_drawer"
		android:layout_width="300dp"
		android:layout_height="match_parent"
		android:layout_gravity="start"
		android:background="# fff"
		android:choiceMode="singleChoice"
		android:divider="# e3e3e3"
		android:dividerHeight="0.1dp" />
</android.support.v4.widget.DrawerLayout>
  • Legen Sie nun eine drawer_list_item.xml Datei im layout Ordner an und kopieren Sie diesen Inhalt dort hinein. Diese Datei gibt das Design des Navigation Drawers an.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	style="?attr/spinnerDropDownItemStyle"
	android:layout_width="match_parent"
	android:layout_height="?dropdownListPreferredItemHeight"
	android:orientation="horizontal" >

	<ImageView
		android:id="@+id/icon"
		android:layout_width="wrap_content"
		android:layout_height="match_parent"
		android:adjustViewBounds="true"
		android:paddingLeft="4dp"
		android:paddingRight="4dp"
		android:contentDescription="Entry-Icon" />

	<LinearLayout
		android:layout_width="wrap_content"
		android:layout_height="match_parent"
		android:gravity="center_vertical|left"
		android:minHeight="?listPreferredItemHeightSmall"
		android:orientation="vertical" >

		<TextView
			android:id="@+id/title"
			style="?spinnerDropDownItemStyle"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:ellipsize="end"
			android:textSize="17dp"
			android:singleLine="true" />

		<TextView
			android:id="@+id/subtitle"
			style="?spinnerDropDownItemStyle"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:ellipsize="end"
			android:textSize="13dp"
			android:singleLine="true"
			android:textAppearance="?textAppearanceSmall" />
	</LinearLayout>

</LinearLayout>
  • Nun benötigen Sie noch ein Icon, welches den Navigation Drawer darstellt und einen Schatten, der sich über den Rest der Anwendung legt, falls der Navigation Drawer “ausgefahren” ist. Diese Ressourcen finden Sie im Beispielprojekt.
  • Legen Sie nun eine Klasse namens MenuListAdapter.java an. Diese kümmert sich um die korrekte Darstellung der Elemente im Navigation Drawer.
    Wie Sie hier bereits sehen, sind im Layout Titel, Untertitel und Icons möglich - ein konkretes Beispiel dazu finden Sie oben im letzten Bild.

package de.menzerath.tutorial.navdrawer;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.TextView;

public class MenuListAdapter extends BaseAdapter {
	private Context context;
	private String[] mTitle;
	private String[] mSubTitle;
	private int[] mIcon;
	private LayoutInflater inflater;

	public MenuListAdapter(Context pContext, String[] pTitle, String[] pSubtitle, int[] pIcon) {
		context = pContext;
		mTitle = pTitle;
		mSubTitle = pSubtitle;
		mIcon = pIcon;
	}

	public View getView(int position, View convertView, ViewGroup parent) {
		inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		View itemView = inflater.inflate(R.layout.drawer_list_item, parent, false);

		TextView txtTitle = (TextView) itemView.findViewById(R.id.title);
		TextView txtSubTitle = (TextView) itemView.findViewById(R.id.subtitle);
		ImageView imgIcon = (ImageView) itemView.findViewById(R.id.icon);

		txtTitle.setText(mTitle[position]);
		txtSubTitle.setText(mSubTitle[position]);
		imgIcon.setImageResource(mIcon[position]);

		return itemView;
	}

	@Override
	public int getCount() {
		return mTitle.length;
	}

	@Override
	public Object getItem(int position) {
		return mTitle[position];
	}

	@Override
	public long getItemId(int position) {
		return position;
	}
}
  • Nun geht es an die MainActivity.java. Kopieren Sie dort einfach folgenden Code hinein - die Erklärungen stehen jeweils in Kommentaren.

package de.menzerath.tutorial.navdrawer;

import android.content.res.Configuration;
import android.os.Bundle;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.view.View;
import android.widget.AdapterView;
import android.widget.ListView;
import com.actionbarsherlock.app.SherlockActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;

public class MainActivity extends SherlockActivity {
	private DrawerLayout mDrawerLayout;
	private ListView mDrawerList;
	private ActionBarDrawerToggle mDrawerToggle;
	private CharSequence mTitle;

	private String[] drawerTitles;
	private String[] drawerSubtitles;
	private int[] drawerIcons;

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

		mTitle = getTitle();

		mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
		mDrawerList = (ListView) findViewById(R.id.left_drawer);
		mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);

		// Hole die Titel aus einem Array aus der strings.xml
		drawerTitles = getResources().getStringArray(R.array.drawerTitles_array);
		// Hole die Untertitel aus einem Array aus der strings.xml
		drawerSubtitles = getResources().getStringArray(R.array.drawerSubtitles_array);
		// Setzt die Icons zu den Einträgen
		drawerIcons = new int[] {android.R.drawable.ic_menu_info_details, android.R.drawable.ic_menu_edit, android.R.drawable.ic_menu_delete};

		// Erstellt den neuen MenuAdapter aus der Klasse MenuListAdapter
		MenuListAdapter mMenuAdapter = new MenuListAdapter(this, drawerTitles, drawerSubtitles, drawerIcons);
		mDrawerList.setAdapter(mMenuAdapter);
		mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

		// Bereitet die ActionBar auf den Navigation Drawer vor
		getSupportActionBar().setDisplayHomeAsUpEnabled(true);
		getSupportActionBar().setHomeButtonEnabled(true);

		// Fügt den Navigation Drawer zur ActionBar hinzu
		mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {
			public void onDrawerClosed(View view) {
				getSupportActionBar().setTitle(mTitle);
				supportInvalidateOptionsMenu();
			}

			public void onDrawerOpened(View drawerView) {
				getSupportActionBar().setTitle(R.string.app_name);
				supportInvalidateOptionsMenu();
			}
		};
		mDrawerLayout.setDrawerListener(mDrawerToggle);
	}

	// Fügt das Menü hinzu / ActionBar Einträge
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		MenuInflater inflater = getSupportMenuInflater();
		inflater.inflate(R.menu.main, menu);
		return super.onCreateOptionsMenu(menu);
	}

	// Versteckt die ActionBar-Einträge, sobald der Drawer ausgefahren is
	@Override
	public boolean onPrepareOptionsMenu(Menu menu) {
		boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);
		menu.findItem(R.id.action_settings).setVisible(!drawerOpen);
		return super.onPrepareOptionsMenu(menu);
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Öffnet und schließt den Navigation Drawer bei Klick auf den Titel/das Icon in der ActionBar
		if (item.getItemId() == android.R.id.home) {
			if (mDrawerLayout.isDrawerOpen(mDrawerList)) {
				mDrawerLayout.closeDrawer(mDrawerList);
			} else {
				mDrawerLayout.openDrawer(mDrawerList);
			}
		}

		// Gibt den ActionBar-Buttons Funktionen
		switch (item.getItemId()) {
			case R.id.action_settings:
				// Tu' etwas!
				return true;
			default:
				return super.onOptionsItemSelected(item);
		}
	}

	// Listener für die Navigation Drawer Einträge - Achtung: Zählung beginnt bei 0!
	private class DrawerItemClickListener implements ListView.OnItemClickListener {
		@Override
		public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
			if (position == 0) {
				// Aktion
			} else if (position == 1) {
				// Aktion
			} else if (position == 2) {
				// Aktion
			}

			mDrawerList.setItemChecked(position, true);
			mTitle = drawerTitles[position];
			getSupportActionBar().setTitle(mTitle);
			mDrawerLayout.closeDrawer(mDrawerList);
		}
	}

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

	@Override
	public void onConfigurationChanged(Configuration newConfig) {
		super.onConfigurationChanged(newConfig);
		mDrawerToggle.onConfigurationChanged(newConfig);
	}
}
  • Nun brauchen Sie noch einige Strings und String-Arrays in Ihrer strings.xml Datei und Sie sind fertig. Kopieren Sie dazu einfach diesen Code dort hinein:

<string name="drawer_open">Open navigation drawer</string>
<string name="drawer_close">Close navigation drawer</string>

<string-array name="drawerTitles_array">
	<item>Titel 1</item>
	<item>Toller Titel 2</item>
	<item>Mein dritter Titel</item>
</string-array>
<string-array name="drawerSubtitles_array">
	<item>Untertitel 1</item>
	<item>Toller Untertitel 2</item>
	<item>Mein dritter Untertitel</item>
</string-array>
  • Starten Sie nun einfach das Projekt und Sie haben den Navigation Drawer erfolgreich implementiert! Ihre App sollte nun ein solches Menü aufweisen, wenn Sie den Titel der ActionBar berühren oder von links nach rechts wischen:
    Navigation Drawer: Beispiel

Den Download des Projekts finden Sie hier zur freien Verwendung.

Fazit

Der Navigation Drawer ist eine simple, aber sehr effektive Methode zur Navigation innerhalb Ihrer App - besonders bei der Verwendung von Fragments. Bereits jetzt verwenden viele bekannte Apps diese Möglichkeit der Navigation und begeistern viele Nutzer damit. Wieso nicht auch Sie?