2019独角兽企业重金招聘Python工程师标准>>>

相信Sliding Menu很多人都用过,在Android和iOS的app中,越来越多的开发者都会把自己的菜单界面放在一个列表里,然后让用户通过向右(或者向左)滑动的操作看到应用所有的功能。Google官方的应用也基本都选择了这种交互方式,不同的是,Google使用的是Navigation Drawer,而我们大部分用的还是Sliding Menu。

大家对Sliding Menu这个开源项目可能已经很熟悉了,但是Navigation Drawer我们有些童鞋可能了解的还比较少,它是Google I/O 2013刚推出不久的一个在support v4包里面的一个控件,下面我就通过一个demo跟大家介绍一下Navigation Drawer的使用方法。http://safe.ijiami.cn/

这个demo是google官方的,大家可以到这里下载一下:http://developer.android.com/training/implementing-navigation/nav-drawer.html,我下面写的代码说明也基本就是翻译了一下这个教程,英语比较好的童鞋建议还是直接看官方的吧。

创建一个抽屉

导航抽屉是一个位于屏幕左侧边缘用来显示应用程序导航项的一个面板。导航抽屉在大部分时间是不显示的,但两种情况下会进行显示:一是发生从屏幕左侧边缘向右滑的手势,二是点击了工具栏中应用图标。导航抽屉在SupportLibrary  中提供支持,在使用导航抽屉时,需要符合导航抽屉设计原则(NavigationDrawer),看看你是否有必要创建导航抽屉 。

创建抽屉布局

如果你要添加一个导航抽屉,需要用DrawerLayout来作为用户界面的根视图,DrawerLayout视图下需放置两个子视图,一个是用来显示显示屏幕的主体内容(导航抽屉隐藏的时候),一个是用来显示导航抽屉。

用来显示屏幕主体内容的视图一般是FrameLayout(运行的时候,会被一个Fragment填充),用来显示导航抽屉的视图一般是一个ListView,如下所示

  1. <android.support.v4.widget.DrawerLayout

  2. xmlns:android="http://schemas.android.com/apk/res/android"

  3. android:id="@+id/drawer_layout"

  4. android:layout_width="match_parent"

  5. android:layout_height="match_parent">

  6. <!-- The main content view -->

  7. <FrameLayout

  8. android:id="@+id/content_frame"

  9. android:layout_width="match_parent"

  10. android:layout_height="match_parent" />

  11. <!-- The navigation drawer -->

  12. <ListView android:id="@+id/left_drawer"

  13. android:layout_width="240dp"

  14. android:layout_height="match_parent"

  15. android:layout_gravity="start"

  16. android:choiceMode="singleChoice"

  17. android:divider="@android :color/transparent"

  18. android:dividerHeight="0dp"

  19. android:background="#111"/>

  20. </android.support.v4.widget.DrawerLayout>

复制代码

上面的布局说明了导航抽屉的布局一些非常重要的特点:

1、显示主体内容的视图必须是DrawerLayout下的第一个子视图,因为抽屉视图必须在主体内容视图的上方(意味着DrawerLayout是一个以z轴来布局的控件)

2、显示主体内容的视图必须设置为匹配父视图的高和宽,因为当抽屉视图隐藏的时候显示主体内容的视图代表了整个用户界面

3、抽屉视图的layout_gravity属性值需为“start”,To support right-to-left (RTL) languages,specify the value with "start" insteadof "left" (so the drawer appears on the right when thelayout is RTL)

4、抽屉视图的宽度不宜匹配父视图,应当适当的窄一点,这样就能在抽屉显示的时候还能看到主体内容视图的一部分

初始化抽屉列表

抽屉视图一般包含一个ListView(具体包含的View取决于你的应用),该ListView和平常没什么两样,都需要一个Adapter来填充,也可设置单项选中监听器

  1. public class MainActivity extends Activity {

  2. private String[] mPlanetTitles;

  3. private DrawerLayout mDrawerLayout;

  4. private ListView mDrawerList;

  5. ...

  6. @Override

  7. public void onCreate(Bundle savedInstanceState) {

  8. super.onCreate(savedInstanceState);

  9. setContentView(R.layout.activity_main);

  10. mPlanetTitles = getResources().getStringArray(R.array.planets_array);

  11. mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

  12. mDrawerList = (ListView) findViewById(R.id.left_drawer);

  13. // Set the adapter for the list view

  14. mDrawerList.setAdapter(new ArrayAdapter<String>(this,

  15. R.layout.drawer_list_item, mPlanetTitles));

  16. // Set the list's click listener

  17. mDrawerList.setOnItemClickListener(new DrawerItemClickListener());

  18. ...

  19. }

  20. }

复制代码

处理导航项选点击事件

导航项的点击事件其实就是包含的ListView项的点击事件,我们需要根据点击的项来相应的改变主体内容,记得上面说过显示主体内容的View运行时一般会是一个Fragment,所以只要把当前的Fragment替换成相应的Fragment就行了

  1. private class DrawerItemClickListener implements ListView.OnItemClickListener {

  2. @Override

  3. public void onItemClick(AdapterView parent, View view, int position, long id) {

  4. selectItem(position);

  5. }

  6. }

  7. /** Swaps fragments in the main content view */

  8. private void selectItem(int position) {

  9. // Create a new fragment and specify the planet to show based on position

  10. Fragment fragment = new PlanetFragment();

  11. Bundle args = new Bundle();

  12. args.putInt(PlanetFragment.ARG_PLANET_NUMBER, position);

  13. fragment.setArguments(args);

  14. // Insert the fragment by replacing any existing fragment

  15. FragmentManager fragmentManager = getFragmentManager();

  16. fragmentManager.beginTransaction()

  17. .replace(R.id.content_frame, fragment)

  18. .commit();

  19. // Highlight the selected item, update the title, and close the drawer

  20. mDrawerList.setItemChecked(position, true);

  21. setTitle(mPlanetTitles[position]);

  22. mDrawerLayout.closeDrawer(mDrawerList);

  23. }

  24. @Override

  25. public void setTitle(CharSequence title) {

  26. mTitle = title;

  27. getActionBar().setTitle(mTitle);

  28. }

复制代码

监听导航抽屉打开和关闭事件

可以为DrawerLayout设置 DrawerLayout.DrawerListener监听器来监听打开和关闭事件,当导航抽屉打开和关闭时分别会回调onDrawerOpened() 和onDrawerClosed() 方法

但是如果你的Activity包含Action Bar话,你可以选择 ActionBarDrawerToggle 来替代 DrawerListener ,ActionBarDrawerToggle 实现了DrawerListener接口,所以抽屉的打开和关闭事件照样能监听的到,并且使用ActionBarDrawerToggle能促进Action Bar Icon和导航抽屉之间的交互(通过点击icon来打开和关闭导航抽屉),当导航抽屉打开或关闭时Action Bar的状态也应该做相应的改变( NavigationDrawer 中有介绍)

  1. public class MainActivity extends Activity {

  2. private DrawerLayout mDrawerLayout;

  3. private ActionBarDrawerToggle mDrawerToggle;

  4. private CharSequence mDrawerTitle;

  5. private CharSequence mTitle;

  6. ...

  7. @Override

  8. public void onCreate(Bundle savedInstanceState) {

  9. super.onCreate(savedInstanceState);

  10. setContentView(R.layout.activity_main);

  11. ...

  12. mTitle = mDrawerTitle = getTitle();

  13. mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

  14. mDrawerToggle = new ActionBarDrawerToggle(this, mDrawerLayout,

  15. R.drawable.ic_drawer, R.string.drawer_open, R.string.drawer_close) {

  16. /** Called when a drawer has settled in a completely closed state. */

  17. public void onDrawerClosed(View view) {

  18. getActionBar().setTitle(mTitle);

  19. invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()

  20. }

  21. /** Called when a drawer has settled in a completely open state. */

  22. public void onDrawerOpened(View drawerView) {

  23. getActionBar().setTitle(mDrawerTitle);

  24. invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu()

  25. }

  26. };

  27. // Set the drawer toggle as the DrawerListener

  28. mDrawerLayout.setDrawerListener(mDrawerToggle);

  29. }

  30. /* Called whenever we call invalidateOptionsMenu() */

  31. @Override

  32. public boolean onPrepareOptionsMenu(Menu menu) {

  33. // If the nav drawer is open, hide action items related to the content view

  34. boolean drawerOpen = mDrawerLayout.isDrawerOpen(mDrawerList);

  35. menu.findItem(R.id.action_websearch).setVisible(!drawerOpen);

  36. return super.onPrepareOptionsMenu(menu);

  37. }

  38. }

复制代码

点击应用图标来打开和关闭导航抽屉

前面我们是介绍过通过手势来打开和关闭导航抽屉,但是如果Activity包含Action Bar的话,当我们点击应用图标时也能打开和关闭导航抽屉,而且我们也需要通过图标来指示导航抽屉当前的状态,如果我们是使用ActionBarDrawerToggle类的话,可以通过设置构造方法的参数来做到这一点,它的构造方法参数有五个,分别代表:宿主Activity、DrawerLayout、导航抽屉打开时应用图标、导航抽屉打开时描述文本、导航抽屉关闭时描述文本

还有一点要注意的是,当手机屏幕的配置环境发生变化时(横竖屏切换),导航抽屉的配置也需改变,当宿主Activity的onRestoreInstanceState方法调用的时候,导航抽屉的状态也需进行同步,可在onPostCreate方法中进行同步,具体的可以看如下代码

  1. public class MainActivity extends Activity {

  2. private DrawerLayout mDrawerLayout;

  3. private ActionBarDrawerToggle mDrawerToggle;

  4. ...

  5. public void onCreate(Bundle savedInstanceState) {

  6. ...

  7. mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);

  8. mDrawerToggle = new ActionBarDrawerToggle(

  9. this, /* host Activity */

  10. mDrawerLayout, /* DrawerLayout object */

  11. R.drawable.ic_drawer, /* nav drawer icon to replace 'Up' caret */

  12. R.string.drawer_open, /* "open drawer" description */

  13. R.string.drawer_close /* "close drawer" description */

  14. ) {

  15. /** Called when a drawer has settled in a completely closed state. */

  16. public void onDrawerClosed(View view) {

  17. getActionBar().setTitle(mTitle);

  18. }

  19. /** Called when a drawer has settled in a completely open state. */

  20. public void onDrawerOpened(View drawerView) {

  21. getActionBar().setTitle(mDrawerTitle);

  22. }

  23. };

  24. // Set the drawer toggle as the DrawerListener

  25. mDrawerLayout.setDrawerListener(mDrawerToggle);

  26. getActionBar().setDisplayHomeAsUpEnabled(true);

  27. getActionBar().setHomeButtonEnabled(true);

  28. }

  29. @Override

  30. protected void onPostCreate(Bundle savedInstanceState) {

  31. super.onPostCreate(savedInstanceState);

  32. // Sync the toggle state after onRestoreInstanceState has occurred.

  33. mDrawerToggle.syncState();

  34. }

  35. @Override

  36. public void onConfigurationChanged(Configuration newConfig) {

  37. super.onConfigurationChanged(newConfig);

  38. mDrawerToggle.onConfigurationChanged(newConfig);

  39. }

  40. @Override

  41. public boolean onOptionsItemSelected(MenuItem item) {

  42. // Pass the event to ActionBarDrawerToggle, if it returns

  43. // true, then it has handled the app icon touch event

  44. if (mDrawerToggle.onOptionsItemSelected(item)) {

  45. return true;

  46. }

  47. // Handle your other action bar items...

  48. return super.onOptionsItemSelected(item);

  49. }

  50. ...

  51. }

复制代码

几张运行的截图:

转载于:https://my.oschina.net/1590538xiaokai/blog/324628

Navigation Drawer详解-Google推出的用来取代Sliding Menu的控件(一相关推荐

  1. Visual C++网络编程经典案例详解 第9章 实用播放器 界面初始化 tab控件初始化 InsertItem()原型

    如果启动后 没有响应歌曲 则tab控件提示用户 播放器没有歌曲要添加歌曲 否则播放歌曲 添加成员变量对话框修改变量名称为m_tab 使用CTabCtrl类对象m_tab在TAB控件中添加属性页 Ins ...

  2. 详解Google第二代TPU 既能推理又能训练 性能霸道

    详解Google第二代TPU 既能推理又能训练 性能霸道 转自:http://www.cnbeta.com/articles/tech/613639.htm 5月18日凌晨,Google CEO Su ...

  3. 详解Google Authenticator工作原理

     详解Google Authenticator工作原理 发表于2014-09-23 08:28| 10060次阅读| 来源CSDN| 16 条评论| 作者伍昆 Google二维码Google Au ...

  4. gms认证流程_【热点资讯】详解Google GMS认证流程可大大缩短终端手机上市时间...

    原标题:[热点资讯]详解Google GMS认证流程可大大缩短终端手机上市时间 继联发科在2017年11月宣布正式进入谷歌的GMS Express项目后,日前紫光展锐也宣布了同样的计划,成为本土第一个 ...

  5. Android 官方架构组件 Navigation 使用详解

    前言 前段时间,我在做项目开发的时候对Fragment的管理遇到几个小问题,总觉得在现阶段封装好的Fragment管理器不太优雅.这成为我下决心学习Jetpack在很早之前推出的Navigation库 ...

  6. Facebook力推导航库:React Navigation使用详解

    本文来自Songlcy投稿:文章地址:http://blog.csdn.net/u013718120/article/details/72357698 一.开源库介绍 今年1月份,新开源的react- ...

  7. Flutter Drawer详解

    文章目录 简介 基础属性 DrawerHeader UserAccountsDrawerHeader 功能列表 Drawer打开关闭 完整代码 效果: 简介 Drawer是一个抽屉控件,通常从页面的左 ...

  8. Android | navigation入门详解

    本文来自博客园,作者:{观心静},转载请注明原文链接: {https://www.cnblogs.com/guanxinjing/} 本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此 ...

  9. 万字详解 Google Play 上架应用标准包格式 AAB

    应用出海绕不开 Google Play 这个核心渠道.关注[融云全球互联网通信云]了解更多 根据数据平台 Statcounter 的数据,截至 2022 年 6 月,Android 在全球移动设备操作 ...

最新文章

  1. 如何将RDS的数据同步到本地自建数据库
  2. 戏说 Windows GDI (3)
  3. 使用指针数组实现这两个矩阵的相乘
  4. html5中底部对齐怎么写,如何将页脚(div)与页面底部对齐?
  5. GA,RC,Alpha,Beta,Final等软件版本名词释义
  6. java服务器端测试_java-在服务器端测试Spring Web Services端点?
  7. 微型计算机发展方向网络化,第二章 会计电算化工作环境
  8. SPI协议通信时序详解
  9. COMSOL:案列应用实操教学---光电
  10. PackageManager的基本使用
  11. python中image库_python Image库使用入门
  12. Mathematica 分段函数 求导 求积分
  13. an error occurred while creating opening the c++ browsing database 解决办法
  14. python和java可以一起学吗_python可以和java一起学吗
  15. 平面设计零基础怎么设计出一个完美的名片
  16. Python VUE3 + Django Ninja的后台管理系统
  17. 微信小程序websocket连接
  18. golang: Google Play退款订单数据查询
  19. 自动给多个视频进行画面裁切,裁剪成一样的尺寸
  20. channel error; protocol method: #method<channel.close>(reply-code=406, reply-text=PRECONDITION_FAILE

热门文章

  1. 8s yaml 配置生成_cfg4py:一个严肃的Python配置模块应有的风格-层级式、部署环境自适应、自动补全...
  2. 《移山之道》第十一章:两人合作 读书笔记 PB16110698 第六周(~4.15)
  3. PhpStorm 2017 for Mac 汉化
  4. 22. Generate Parentheses
  5. Docker Inspect
  6. 【CV论文阅读】 Fast RCNN + SGD笔记
  7. 关于storm0.10.0版本的一个小bug
  8. POJ 1611 The Suspects
  9. SharePoint服务器修改域和机器名
  10. [转]JavaScript var obj = { id:1, name:jacky } 大括号是啥意思?