导航的抽屉是一个在屏幕的左边缘显示应用程序的主导航选项的面板。大部分时间它是隐藏的,但当用户使用手指从屏幕的左边缘滑动时,或者当用户触摸action bar上的app 图标时,它就会显示。
导航抽屉设计
在你决定在你的APP里用导航抽屉之前,你应该理解导航抽屉设计向导的设计用例和设计原则
创建一个DrawerLayout
添加导航的抽屉,声明一个用drawerlayout对象作为你布局的root view的UI。在drawerlayout里,添加一个view包含屏幕的主要内容(当抽屉隐藏时,做为你的主要布局)和另一种view,包含导航抽屉里的内容。
例如,下面的layout 使用drawerlayout有两个子view:一个FrameLayout包含的主要内容(运行时作用在一个Fragment上),和一个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>
这种布局演示了一些重要的布局特点:
1,主要内容视图(FrameLayout上)必须是drawerlayout的第一个子view,因为XML的命令意味着属性与抽屉必须在上面的内容。
2,主要内容视图的宽度,高度设置为match_parent,因为当导航抽屉隐藏时它代表了整个UI。
3,抽屉里的view(ListView)必须指定android:layout_gravity属性。支持从右到左(RTL)语言,指定的值是“start”而不是“left”(所以抽屉右侧出现时的布局是RTL)。
4,抽屉视图指定他的宽度用DP和高度是match_parent。抽屉的宽度不应超过320dp以便用户可以一直看到主要的内容的一部分。
在你的activity,首先要做的是初始化导航抽屉list的item。你如何做取决于你的应用程序的内容,但是一个导航抽屉包括一个ListView列表,所以list应该由一个适配器(如ArrayAdapter或simplecursoradapter)。
例如,在这里你可以初始化一个字符串数组的list:
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());
...
}
}
你在onitemclick()方法上做什么取决于你如何设计你的应用程序的结构。在下面的例子里,选择每个item都会插入一个不同的Fragment在主界面(FrameLayout的要素取决他的Id(R.id.content_frame)):
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);
}
监听抽屉的打开和关闭事件,在你的rawerlayout里设置 setdrawerlistener()和通过它来实现drawerlayout.drawerlistener。这个接口提供了抽屉事件的回调比如ondraweropened()和ondrawerclosed()。
然而,与其实现drawerlayout.drawerlistener,如果你的activity包含action bar,你可以继承actionbardrawertoggle类。该actionbardrawertoggle实现了drawerlayout.drawerlistener。因此,你仍然可以复写这些回调,但它也有利于动作栏图标和导航的抽屉之间的交互行为(接下来讨论)。
在导航抽屉设计指南中讨论的,当抽屉是可见时,你应该修改你的action bar的内容,如更改标题和删除action items的主要内容。下面的代码显示了如何可以通过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.drawable.ic_drawer, 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构造器的参数和其他需要设置的步骤来与action bar图标的交互。
打开和关闭 应用程序图标
用户可以通过滑动手势从屏幕的左边缘或者向屏幕的左边缘来打开和关闭导航抽屉,但是如果你用了action bar,你也应该允许用户通过应用程序图标的图标来打开和关闭它。应用程序图标也应该用一个特殊的图标表明导航抽屉的存在。你可以通过使用上面所示的actionbardrawertoggle实现这一切行为。
为了让ActionBarDrawerToggle可以用,通过他的构造器创造一个实力,这需要下列参数:
activity的抽屉。
该drawerlayout。
一个Drawable资源作为抽屉指示器。
标准的导航图标抽屉在动作栏图标包可供下载。
一个字符串资源来描述“打开抽屉”行动(可达性)。
一个字符串资源来描述“关闭抽屉”行动(可达性)。
那么,无论你是否创建了actionbardrawertoggle的子类作为你的抽屉的listener,你需要调用你的actionbardrawertoggle在一些地方在你的activity的生命周期:
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.drawable.ic_drawer, /* nav drawer icon to replace 'Up' caret */
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);
}
...
}
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。