如需转载请注明出处: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. 转载--CentOS 6.3下部署LVS(NAT)+keepalived实现高性能高可用负载均衡

    源地址:http://www.cnblogs.com/mchina/archive/2012/08/27/2644391.html 一.简介 VS/NAT原理图: 二.系统环境 实验拓扑: 系统平台: ...

  2. [Node.js] Promise,Q及Async

    原文地址:http://www.moye.me/2014/12/27/promise_q_async/ 引子 在使用Node/JS编程的时候,经常会遇到这样的问题:有一连串的异步方法,需要按顺序执行, ...

  3. [git]解决rebase冲突

    git pull --rebase时产生冲突 有三个选项: git rebase --skip 效果是:抛弃本地的commit,采用远程的commit(慎用因为你本地的修改就会都没有!) git re ...

  4. Scrum1.2--spring计划

    项目功能--深入分析  燃尽图

  5. C#设计模式——策略模式(Strategy Pattern)

    一.概述我们来实现一个企业的工资系统,该企业中不同级别的员工工资算法都不相同,针对该问题,最容易想到的莫过于在代码中堆积一大堆if…else…语句或者是switch…case…语句.如果该企业中不同级 ...

  6. 在android设备上调试ionic应用

    方法1: ionic run android -l -c 将会在console中输出日志信息 方法2: (1).使用usb连接android设备,并打开android设备的调试功能 (2).在chro ...

  7. Winform开发框架之权限管理系统改进的经验总结(2)-用户选择界面的设计

    在上篇总结随笔<Winform开发框架之权限管理系统改进的经验总结(1)-TreeListLookupEdit控件的使用>介绍了权限管理模块的用户管理部分,其中主要介绍了其中的用户所属公司 ...

  8. jquery实现网页选项卡

    这个功能在现在的网站中使用较为普遍,就是以选项卡的形式来对一些内容做了分类.,比如下面的天猫商城. 下面的源码是仿照天猫写的一个选项卡,实现起来的效果如下. 主要是利用我们在点击相应板块是触发它的单击 ...

  9. 【Unity】12.5 Navmesh Obstacle组件

    开发环境:Win10.Unity5.3.4.C#.VS2015 创建日期:2016-05-09 一.简介 在大多数游戏情景中,可行进的区域往往不是完全不变的.比如被破坏的路.桥等将不再允许通过.那么, ...

  10. C# 之屏幕找图

    引言 最近,由于工作上的某些原因,又要写类似于外挂的程序,又要用到一个屏幕找图功能,很多程序(eg:按键精灵)都提供了类似的功能,其实在这之前,我也查找过很多类似的C#方法,因为之前有一个试过没有用得 ...