【原创+译文】官方文档中声明的如何创建抽屉导航栏(Navigation Drawer)
如需转载请注明出处: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)的更多相关文章
- swift官方文档中的函数闭包是怎么理解的?
官方文档中的16页: numbers.map({ (number: Int) -> Int in let result = * number return result }) 不知道这个怎么用, ...
- swift官方文档中的switch中case let x where x.hasSuffix("pepper")是什么意思?
在官方文档中,看到这句.但不明白什么意思. let vegetable = "red pepper" switch vegetable { case "celery&qu ...
- 从官方文档中探索MySQL分页的几种方式及分页优化
概览 相比于Oracle,SQL Server 等数据库,MySQL分页的方式简单得多了,官方自带了分页语法 limit 语句: select * from test_t LIMIT {[offset ...
- tensorflow官方文档中的sub 和mul中的函数已经在API中改名了
在照着tensorflow 官方文档和极客学院中tensorflow中文文档学习tensorflow时,遇到下面的两个问题: 1)AttributeError: module 'tensorflow' ...
- 【采坑小计】thanos receiver的官方文档中,并未说明tsdb落盘的配置方式
官方文档的地址在:https://thanos.io/tip/components/receive.md/ 一开始以为落盘的时间间隔是:--tsdb.retention=15d 实际测试中发现,tha ...
- Django1.7官方文档中的tutorial——翻译
写下你的第一个Django应用,第一部分 让我们通过例子来学习. 通过这篇指南,我们将会带你浏览一遍一个基本投票应用的创建. 它由两部分组成: 1一个让人们查看投票和进行投票的公共站点 2一个让你添加 ...
- Vue官方文档中的camelCased (驼峰式) 命名与 kebab-case
因为html特性中 元素的 prop是不区分大小写的 所以不管html中怎么大写小写变化,下面的组件的prop应该写成小写 Vue中有这样一种设定: props中如果使用为kebab-case命名方式 ...
- 【Rust】使用HashMap解决官方文档中的闭包限制
问题概述 值缓存是一种更加广泛的实用行为,我们可能希望在代码中的其他闭包中也使用他们.然而,目前 Cacher 的实现存在两个小问题,这使得在不同上下文中复用变得很困难. 第一个问题是 Cacher ...
- 摘录ECMAScript官方文档中重要的两段话
Every object created by a constructor has an implicit reference (called the object’s prototype) to t ...
随机推荐
- django 快速实现session的操作
说明: 从这一篇开始就不再完整的介绍django项目的创建过程了,因为前面几篇博客中都详细的介绍了这个创建过程,套路都是一样的,熟悉了这个套路,后面要做的是一些细节技术点的学习和练习. 上一节讲到了d ...
- Nightwatch.js – 轻松实现浏览器的自动测试
Nightwatch.js 是一个易于使用的,基于 Node.js 平台的浏览器自动化测试解决方案.它使用强大的 Selenium WebDriver API 来在 DOM 元素上执行命令和断言. 语 ...
- SQL Server临界点游戏——为什么非聚集索引被忽略!
当我们进行SQL Server问题处理的时候,有时候会发现一个很有意思的现象:SQL Server完全忽略现有定义好的非聚集索引,直接使用表扫描来获取数据.我们来看看下面的表和索引定义: CREATE ...
- HT图形组件设计之道(三)
上篇我们通过定制了CPU和内存展示界面,体验了HT for Web通过定义矢量实现图形绘制与业务数据的代码解耦及绑定联动,这类案例后续文章还会继续以便大家掌握更多的矢量应用场景,本篇我们先切换个话题, ...
- JS魔法堂:浏览器模式和文档模式怎么玩?
一.前言 从IE8开始引入了文档兼容模式的概念,作为开发人员的我们可以在开发人员工具中通过“浏览器模式”和“文档模式”(IE11开始改为“浏览器模式”改成更贴切的“用户代理字符串”)品味一番,它的出现 ...
- ThroughRain第二次冲刺总结
团队名:ThroughRain 项目确定:<餐厅到店点餐系统> 项目背景:本次项目是专门为餐厅开发的一套订餐系统.大家有没有发现在节假日去餐厅吃饭会超级麻烦,人很多, 热门的餐厅基本没有座 ...
- MySQL字符串转日期类型
MySQL字符串转日期类型 select str_to_date('2014-08-20 00:00:00', '%Y-%m-%d %H:%i:%s'); >2014-08-20 00:00:0 ...
- Build 2016概览
很快Microsoft Build 2016马上就要开始,在直播放出来之前,微软已经提前把本次大会期间的所有课程列表放了出来,你可以在这里看到: https://channel9.msdn.com/E ...
- Unity3D入门基本概念整理
1. (1)在场景中添加资源 只需单击工程视图 (Project View) 中的网格(Mesh)并拖动至层级视图 (Hierarchy) 或场景视图 (Scene View),便可将其添加至场景 ( ...
- Repeater控件使用(含删除,分页功能)
Repeater控件使用(含删除,分页功能) 摘自:http://www.cnblogs.com/alanliu/archive/2008/02/25/914779.html 前臺代碼 <%@ ...