如需转载请注明出处:http://www.cnblogs.com/ghylzwsb/p/5831759.html

创建一个抽屉导航栏

抽屉式导航栏是显示在屏幕的左边缘,它是应用程序的主导航选项面板。它大部分时间是处于隐藏状态的,但是当用户从屏幕的左边缘挥动手指时它就会显示出来,而在应用程序的顶层,用户触摸操作栏上的应用程序图标也可以将其显示出来。

本课程介绍在可用的API 支持库下如何实现导航抽屉DrawerLayout。

首先我们可以看一下最终的效果图:

1、创建一个抽屉布局文件(Drawer Layout)

要添加一个抽屉式导航,首先你必须要声明你的用户界面的根布局为DrawerLayout对象。在DrawerLayout里面,添加一个主视图内容的view对象(当抽屉被隐藏的时候显示在屏幕上的 视图)和另外一个包含抽屉导航视图的view对象。

例如,下面的布局采用了包含两个子视图的DrawerLayout:一个是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" > <!-- 主视图 -->
<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:background="#111"
android:choiceMode="singleChoice"
android:divider="@android:color/transparent"
android:dividerHeight="0dp" /> </android.support.v4.widget.DrawerLayout>

这个布局文件演示了一些比较重要的布局特点,如下:

  • 主内容视图(上面的FrameLayout)必须是DrawerLayout布局对象的第一个子view对象,这是因为xml文件意味着是z排序(即空间上的上下排序,也就是说抽屉导航栏应该位于住内容视图的垂直上方)。
  • 主内容视图的view对象的两个属性:layout_width、layout_height必须是match_parent的,这是因为当抽屉导航栏被隐藏的时候他便是整个UI。
  • 抽屉视图要指定其宽度的单位为dp,高度与父视图相匹配。抽屉的宽度应该不超过320dp,这样用户可以随时看到主要内容视图的一些部分。
  • 抽屉视图(ListView)必须用 android:layout_gravity 属性来指定他的水平重力方向。为了支持从右到左(RTL)的语言,应该要指定其属性为"start" ,而不是"left" 。

2、初始化抽屉列表

在你的Activity中,首先要做的事之一就是初始化抽屉导航栏中的列表项。至于你要如何做取决于你的应用程序中的内容,但是通常情况下抽屉导航栏都是包含了一个ListView,所以列表应该由Adapter来填充(如ArrayAdapter或者SimpleCursorAdapter)。

例如下面将告诉你如何用字符串数组初始化抽屉导航栏列表:

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()来接收抽屉导航栏列表的点击事件。下一节将展示如何实现此接口,以实现当用户选择一个项目后更改主内容视图。

3、处理导航的点击事件

当用户选择在抽屉导航栏里列表中的项目时,系统调用OnItemClickListener接口中的onItemClick()方法以返回给OnItemClickListener() 。你要在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);
}

4、监听打开以及关闭抽屉导航栏的事件

要监听抽屉打开和关闭事件,在你的DrawerLayout中调用setDrawerListener()并传入一个DrawerLayout.DrawerListener接口 。此接口为抽屉导航栏提供了回掉方法,如onDrawerOpened()和onDrawerClosed()。

然而,除了实现DrawerLayout.DrawerListener接口之外,如果你的Activity包含了ActionBar,你也可以继承ActionBarDrawerToggle这个类,这是因为ActionBarDrawerToggle类实现DrawerLayout.DrawerListener接口,所以你仍然可以复写这些方法,但是这对ActionBar图标和抽屉的交互也有一定的帮助。

正如在抽屉导航设计指南讨论的一样,当抽屉处于可见状态时你应该要修改操作栏(ActionBar)的内容,例如你应该要改变标题,并移除与主内容试图相关的列表项。下面的代码演示了如何通过实例化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构造函数的参数,并设置它来处理与操作栏图标交互所需的其他步骤。

5、如何通过应用程序图标打开或关闭抽屉导航栏

用户可以通过来自或朝向屏幕的左边缘轻扫的手势来打开与关闭抽屉式导航栏,但如果你正在使用操作栏(ActionBar) ,你也应该允许用户通过触摸应用程序图标的方式打开或者关闭抽屉导航栏。而应用程序图标也应用一个特殊的图标注明抽屉的存在。你也可以通过实现上一节讲到的ActionBarDrawerToggle来实现这些行为。

为了使ActionBarDrawerToggle发挥作用,你将需要创建它的一个实例与它的构造方法,这需要下列参数:

  • 持有该抽屉的Activity
  • 一个DrawerLayout
  • 用于作为抽屉指标的绘制资源(drawable resource),这里会提供一个android官方提供的图标包:Android_Design_Icons_20130926.zip
  • 用来形容“打开抽屉”这一操作的字符串资源
  • 用来形容“关闭抽屉”这一操作的字符串资源

最后,不管你是否已经创建了ActionBarDrawerToggle的子类作为抽屉的监听器,你还是需要在整个Activity的生命周期中的几个地方调用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.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);
} ...
}

教程的最后,我提供了项目的下载地址:DrawerLayout_sample.rar,希望这个教程能够帮到你。

BOB

2016-09-03

【原创+译文】官方文档中声明的如何创建抽屉导航栏(Navigation Drawer)的更多相关文章

  1. swift官方文档中的函数闭包是怎么理解的?

    官方文档中的16页: numbers.map({ (number: Int) -> Int in let result = * number return result }) 不知道这个怎么用, ...

  2. swift官方文档中的switch中case let x where x.hasSuffix("pepper")是什么意思?

    在官方文档中,看到这句.但不明白什么意思. let vegetable = "red pepper" switch vegetable { case "celery&qu ...

  3. 从官方文档中探索MySQL分页的几种方式及分页优化

    概览 相比于Oracle,SQL Server 等数据库,MySQL分页的方式简单得多了,官方自带了分页语法 limit 语句: select * from test_t LIMIT {[offset ...

  4. tensorflow官方文档中的sub 和mul中的函数已经在API中改名了

    在照着tensorflow 官方文档和极客学院中tensorflow中文文档学习tensorflow时,遇到下面的两个问题: 1)AttributeError: module 'tensorflow' ...

  5. 【采坑小计】thanos receiver的官方文档中,并未说明tsdb落盘的配置方式

    官方文档的地址在:https://thanos.io/tip/components/receive.md/ 一开始以为落盘的时间间隔是:--tsdb.retention=15d 实际测试中发现,tha ...

  6. Django1.7官方文档中的tutorial——翻译

    写下你的第一个Django应用,第一部分 让我们通过例子来学习. 通过这篇指南,我们将会带你浏览一遍一个基本投票应用的创建. 它由两部分组成: 1一个让人们查看投票和进行投票的公共站点 2一个让你添加 ...

  7. Vue官方文档中的camelCased (驼峰式) 命名与 kebab-case

    因为html特性中 元素的 prop是不区分大小写的 所以不管html中怎么大写小写变化,下面的组件的prop应该写成小写 Vue中有这样一种设定: props中如果使用为kebab-case命名方式 ...

  8. 【Rust】使用HashMap解决官方文档中的闭包限制

    问题概述 值缓存是一种更加广泛的实用行为,我们可能希望在代码中的其他闭包中也使用他们.然而,目前 Cacher 的实现存在两个小问题,这使得在不同上下文中复用变得很困难. 第一个问题是 Cacher  ...

  9. 摘录ECMAScript官方文档中重要的两段话

    Every object created by a constructor has an implicit reference (called the object’s prototype) to t ...

随机推荐

  1. NopCommerce之事件通知

    mark下,等下写了. NewsController 控制器NewsCommentAdd()缓存清除,使用到了事件

  2. [python]python元类

    这两天在看Django框架,里面的filter实现原理搞不明白,最后发现跟python的元类有关系. 原文:http://stackoverflow.com/questions/100003/what ...

  3. SQL Server中的事务日志管理(5/9):完整恢复模式里的日志管理

    当一切正常时,没有必要特别留意什么是事务日志,它是如何工作的.你只要确保每个数据库都有正确的备份.当出现问题时,事务日志的理解对于采取修正操作是重要的,尤其在需要紧急恢复数据库到指定点时.这系列文章会 ...

  4. Android中的依赖问题(五种依赖、eclipse、AS、添加第三方库、jar)

    这篇文章的主题是: 依赖是什么 eclipse中的依赖 AS中的依赖(有一篇详细的文章讲得非常好,这里就不再写了http://blog.csdn.net/yy1300326388/article/de ...

  5. 12 19 spring3 项目总结

    项目截图: 林集团 https://home.cnblogs.com/u/linjituan/ 团队guihub: https:///github.com/MoiGi 李鹏飞 https://www. ...

  6. STL --- UVA 123 Searching Quickly

    UVA - 123 Searching Quickly Problem's Link:   http://acm.hust.edu.cn/vjudge/problem/viewProblem.acti ...

  7. Linq专题之创建Linq查询表达式

    本节我们主要介绍一下如何创建查询集合类型,关系数据库类型,DataSet对象类型和XML类型的数据源的Linq查询表达式. 下面在实例代码ReadyCollectionData()函数创建了准备的数据 ...

  8. asp.net的code-Behind技术

    新建一个VS.NET下的项目..看到ASPX,RESX和CS三个后缀的文件了吗??这个就是代码分离.实现了HTML代码和服务器代码分离.方便代码编写和整理. code-Behind:asp.net中的 ...

  9. sql 事务使用

    BEGIN TRAN Tran_Money --开始事务 DECLARE @tran_error int; SET @tran_error = 0; BEGIN TRY UPDATE tb_Money ...

  10. String系列

    String 简介 String 是java中的字符串,它继承于CharSequence.String类所包含的API接口非常多.为了便于今后的使用,我对String的API进行了分类,并都给出的演示 ...