转载请注明出处: http://blog.csdn.net/allen315410/article/details/42914501

概述

今天这篇博客将记录一些关于DrawerLayout的基本用法,我想关于DrawerLayout的用法也许有不少不够了解,这也是比较正常的事情,因为DrawerLayout作为Android组件是Google后来在android中添加的,在android.support.v4包下。那么,DrawerLayout是一个怎么的组件呢?我们知道,当我们使用Android上各类App的时候,是不是注意过App主页上通常有一个“侧滑菜单”?关于侧滑菜单的实现,我在前面博客里有一些介绍,想多些了解的朋友请移步:

Android自定义控件——侧滑菜单

Android自定义控件——开源组件SlidingMenu的项目集成

这里用“网易新闻”客户端v4.4的截图来说明一下,这个DrawerLayout抽屉式布局是什么样子的。

   

好,大家已经看到了,网易新闻客户端效果很明显,当我们手指在屏幕左侧向右滑动时候,就会有一个抽屉式的菜单从左边弹出,并且是“悬浮”在主界面之上的,合理的利用了设备上有限的空间,同样手指在屏幕右侧向左滑动也会出现一个向左弹出的抽屉式菜单,用户体验效果还是不错的,在DrawerLayout出现之前,我们需要做侧滑菜单时,不得不自己实现一个或者使用Github上的开源的项目SlidingMenu,也许是Google也看到了SlidingMenu的强大之处,于是在Android的后期版本中添加了DrawerLayout来实现SlidingMenu同样功能的组件,而且为了兼容早期版本,将其添加在android,support.v4包下。

关于DrawerLayout的Training:http://developer.android.com/training/implementing-navigation/nav-drawer.html

关于DrawerLayout的API:http://developer.android.com/reference/android/support/v4/widget/DrawerLayout.html

另外,我已经翻译过了Google的Training课程,地址是:http://blog.csdn.net/allen315410/article/details/42875231

效果预览

创建抽屉布局

下面这个抽屉布局引用的是android.support.v4.DrawerLayout,类似于LineaLayout、RelativeLayout等布局一样定义,在DrawerLayout内部再定义3个布局,分别是管理主界面的FrameLayout,此布局用来展示界面切换的Fragment,下面是ListView,用来展示菜单列表,最后是一个RelativeLayout,用来展示右边的布局,布局代码如下:

[html] view plaincopyprint?
  1. <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. android:id="@+id/drawer_layout"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent" >
  5. <FrameLayout
  6. android:id="@+id/content_frame"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent" />
  9. <ListView
  10. android:id="@+id/left_drawer"
  11. android:layout_width="200dp"
  12. android:layout_height="match_parent"
  13. android:layout_gravity="start"
  14. android:background="#111"
  15. android:choiceMode="singleChoice"
  16. android:divider="@android:color/transparent"
  17. android:dividerHeight="0dp" />
  18. <RelativeLayout
  19. android:id="@+id/right_drawer"
  20. android:layout_width="220dp"
  21. android:layout_height="match_parent"
  22. android:layout_gravity="end"
  23. android:background="#111"
  24. android:gravity="center_horizontal" >
  25. <TextView
  26. android:layout_width="wrap_content"
  27. android:layout_height="wrap_content"
  28. android:text="这是右边栏"
  29. android:textColor="@android:color/white"
  30. android:textSize="24sp" />
  31. </RelativeLayout>
  32. </android.support.v4.widget.DrawerLayout>

这个布局文件示范了一些重要的布局特征.

  • 主要内容的视图(FrameLayout)必须是DrawLayout的第一个子元素, 因为导航抽屉是在主要内容视图的上面.
  • 主要内容视图设置为匹配父视图的宽度和高度, 因为它代表了整个界面导航抽屉是隐藏的.
  • 抽屉视图(ListView)必须指定其水平重力与android:layout_gravity属性。支持从右到左(RTL)语言,指定值与 "start" 代替 "left"(所以抽屉里出现在布局的右侧当布局是RTL时).这里将ListView设置为左边栏菜单,所以android:layout_gravity属性设置为“start”,将RelativeLayout设置为右边栏,设置android:layout_gravity属性为“end”.
  • 抽屉视图指定其宽度用dp单位和高度匹配父视图。抽屉里的宽度不能超过320 dp, 所以用户总是可以看到主要内容视图的一部分。

初始化抽屉列表

正如上述所讲,因为DrawerLayout里包含一个ListView作为左边栏侧滑菜单,所以我们需要首先初始化这个抽屉列表,并且为这个列表适配上数据,数据适配器使用的是最简单的ArrayAdapter,模拟数据被简单的定义在res/values/strings.xml里,如下:

[html] view plaincopyprint?
  1. <string-array name="menu_array">
  2. <item>Menu 1</item>
  3. <item>Menu 2</item>
  4. <item>Menu 3</item>
  5. <item>Menu 4</item>
  6. </string-array>

在Java代码中,首先创建一个MainActivity继承了android.support.v4.app.FragmentActivity,因为后续中需要进行Fragment之间的切换。

[java] view plaincopyprint?
  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. setContentView(R.layout.activity_main);
  4. ......
  5. // 初始化菜单列表
  6. mMenuTitles = getResources().getStringArray(R.array.menu_array);
  7. mMenuListView.setAdapter(new ArrayAdapter<String>(this, R.layout.drawer_list_item, mMenuTitles));
  8. mMenuListView.setOnItemClickListener(new DrawerItemClickListener());
  9. ......
  10. }

处理导航点击事件

当用户选择了抽屉列表里面的一个Item时, 系统调用onItemClickListener上的onItemClick(), 给setOnItemClickListener()你在onItemClick()方法里面做什么,在下面的例子中, 选择每一个Item都会在主要内容的布局中插入一个不同的Fragment.并且将导航列表的内容传递给Fragment中显示出来,下面是部分代码:

[java] view plaincopyprint?
  1. /**
  2. * ListView上的Item点击事件
  3. *
  4. */
  5. private class DrawerItemClickListener implements ListView.OnItemClickListener {
  6. @Override
  7. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  8. selectItem(position);
  9. }
  10. }
  11. /**
  12. * 切换主视图区域的Fragment
  13. *
  14. * @param position
  15. */
  16. private void selectItem(int position) {
  17. // TODO Auto-generated method stub
  18. Fragment fragment = new ContentFragment();
  19. Bundle args = new Bundle();
  20. switch (position) {
  21. case 0:
  22. args.putString("key", mMenuTitles[position]);
  23. break;
  24. case 1:
  25. args.putString("key", mMenuTitles[position]);
  26. break;
  27. case 2:
  28. args.putString("key", mMenuTitles[position]);
  29. break;
  30. case 3:
  31. args.putString("key", mMenuTitles[position]);
  32. break;
  33. default:
  34. break;
  35. }
  36. fragment.setArguments(args); // FragmentActivity将点击的菜单列表标题传递给Fragment
  37. FragmentManager fragmentManager = getSupportFragmentManager();
  38. fragmentManager.beginTransaction().replace(R.id.content_frame, fragment).commit();
  39. // 更新选择后的item和title,然后关闭菜单
  40. mMenuListView.setItemChecked(position, true);
  41. setTitle(mMenuTitles[position]);
  42. mDrawerLayout.closeDrawer(mMenuListView);
  43. }

开源material-menu的集成

细心的朋友也许会发现“网易新闻”v4.4客户端主页左上角上有个菜单“动态”的菜单按钮,显示流程是这样的,当菜单没有打开时,显示“三”这样的三条横线,当菜单打开(无论左右菜单)时,会显示“<-”这样的按钮,不停的变化,这样的效果是不是有点绚丽啊?!了解过Android5.0的朋友,应该会知道这种效果是使用了Android5.0新推出的Material Design设计语言做出来的效果,那么该怎么模仿这个效果呢?不好意思,由于偷懒,我已经在牛牛的Github中找到了这样的效果——material-menu组件,该组件模拟出了Android5.0下的Material Design效果,注意的是该组件中使用了JackWharton的NineOldAndroids动画效果。

material-menu主页:https://github.com/balysv/material-menu

NineOldAndroids主页:https://github.com/JakeWharton/NineOldAndroids

关于material-menu的使用可以参考其主页上的Demo和说明,集成时需要下载NineOldAndroids导出jar集成到项目中。下面是我使用的部分代码:

[java] view plaincopyprint?
  1. protected void onCreate(Bundle savedInstanceState) {
  2. super.onCreate(savedInstanceState);
  3. setContentView(R.layout.activity_main);
  4. ......
  5. // 设置抽屉打开时,主要内容区被自定义阴影覆盖
  6. mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
  7. // 设置ActionBar可见,并且切换菜单和内容视图
  8. getActionBar().setDisplayHomeAsUpEnabled(true);
  9. getActionBar().setHomeButtonEnabled(true);
  10. mMaterialMenuIcon = new MaterialMenuIcon(this, Color.WHITE, Stroke.THIN);
  11. mDrawerLayout.setDrawerListener(new DrawerLayout.SimpleDrawerListener() {
  12. @Override
  13. public void onDrawerSlide(View drawerView, float slideOffset) {
  14. showView = drawerView;
  15. if (drawerView == mMenuListView) {
  16. mMaterialMenuIcon.setTransformationOffset(MaterialMenuDrawable.AnimationState.BURGER_ARROW, isDirection_left ? 2 - slideOffset : slideOffset);
  17. } else if (drawerView == right_drawer) {
  18. mMaterialMenuIcon.setTransformationOffset(MaterialMenuDrawable.AnimationState.BURGER_ARROW, isDirection_right ? 2 - slideOffset : slideOffset);
  19. }
  20. }
  21. @Override
  22. public void onDrawerOpened(android.view.View drawerView) {
  23. if (drawerView == mMenuListView) {
  24. isDirection_left = true;
  25. } else if (drawerView == right_drawer) {
  26. isDirection_right = true;
  27. }
  28. }
  29. @Override
  30. public void onDrawerClosed(android.view.View drawerView) {
  31. if (drawerView == mMenuListView) {
  32. isDirection_left = false;
  33. } else if (drawerView == right_drawer) {
  34. isDirection_right = false;
  35. showView = mMenuListView;
  36. }
  37. }
  38. });
  39. ......
  40. }

此外,还需要关联一下meterial-menu的状态,需要覆盖Activity下的onPostCreate和onSaveInstanceState方法:

[java] view plaincopyprint?
  1. /**
  2. * 根据onPostCreate回调的状态,还原对应的icon state
  3. */
  4. @Override
  5. protected void onPostCreate(Bundle savedInstanceState) {
  6. super.onPostCreate(savedInstanceState);
  7. mMaterialMenuIcon.syncState(savedInstanceState);
  8. }
  9. /**
  10. * 根据onSaveInstanceState回调的状态,保存当前icon state
  11. */
  12. @Override
  13. protected void onSaveInstanceState(Bundle outState) {
  14. mMaterialMenuIcon.onSaveInstanceState(outState);
  15. super.onSaveInstanceState(outState);
  16. }

添加ActionBar上的菜单按钮

为了尽量模拟出“网易新闻”v4.4客户端主页,我也在标题栏右上角添加一个小图标,为了能在点击这个小图标的时候弹出右边栏菜单,实现方式很简单,关于ActionBar上添加导航的知识可以在csdn上搜到一些解释或者上Android开发者官网查看源文档,我这里首先简单的在res/menu下main.xml中这样定义一个:

[html] view plaincopyprint?
  1. <menu xmlns:android="http://schemas.android.com/apk/res/android" >
  2. <item
  3. android:id="@+id/action_personal"
  4. android:icon="@drawable/action_personal"
  5. android:orderInCategory="100"
  6. android:showAsAction="always"
  7. android:title="@string/action_personal"/>
  8. </menu>

完成定义操作后,需要加载菜单布局:

[java] view plaincopyprint?
  1. /**
  2. * 加载菜单
  3. */
  4. @Override
  5. public boolean onCreateOptionsMenu(Menu menu) {
  6. // Inflate the menu; this adds items to the action bar if it is present.
  7. getMenuInflater().inflate(R.menu.main, menu);
  8. return true;
  9. }

标题栏导航点击事件处理

[java] view plaincopyprint?
  1. /**
  2. * 点击ActionBar上菜单
  3. */
  4. @Override
  5. public boolean onOptionsItemSelected(MenuItem item) {
  6. int id = item.getItemId();
  7. switch (id) {
  8. case android.R.id.home:
  9. if (showView == mMenuListView) {
  10. if (!isDirection_left) { // 左边栏菜单关闭时,打开
  11. mDrawerLayout.openDrawer(mMenuListView);
  12. } else {// 左边栏菜单打开时,关闭
  13. mDrawerLayout.closeDrawer(mMenuListView);
  14. }
  15. } else if (showView == right_drawer) {
  16. if (!isDirection_right) {// 右边栏关闭时,打开
  17. mDrawerLayout.openDrawer(right_drawer);
  18. } else {// 右边栏打开时,关闭
  19. mDrawerLayout.closeDrawer(right_drawer);
  20. }
  21. }
  22. break;
  23. case R.id.action_personal:
  24. if (!isDirection_right) {// 右边栏关闭时,打开
  25. if (showView == mMenuListView) {
  26. mDrawerLayout.closeDrawer(mMenuListView);
  27. }
  28. mDrawerLayout.openDrawer(right_drawer);
  29. } else {// 右边栏打开时,关闭
  30. mDrawerLayout.closeDrawer(right_drawer);
  31. }
  32. break;
  33. default:
  34. break;
  35. }
  36. return super.onOptionsItemSelected(item);
  37. }

这段的逻辑有点绕,事实上我做的是这样的,需要保证主界面上只能最多显示一个菜单布局,当左边的菜单布局展示时,此时打开右边菜单布局时,需要隐藏左边菜单布局;同样,如果右边的菜单布局已经在展示的时候,这时需要打开左边菜单布局,必须首先隐藏掉右边的菜单布局。为了判断当前即将显示或者关闭的是哪个布局,我在全局变量中定义了showView用来标记当前即将显示或者关闭的视图,如果showView==mMenuListView,说明左边菜单布局是即将被显示或隐藏的,这时进一步判断菜单是视图mMenuListView的是否已经显示的标记isDirection_left,来打开或者关闭左边视图菜单。
      同样的道理,如果当前即将显示或者隐藏的是右边导航菜单的话,我们需要进一步判断右边导航是否已经显示,从而进行相关打开或隐藏的决定。

这里的逻辑似乎解释的有点乱,而且代码是分片段贴出来的,不利于理解,需要进一步理解的话,不妨继续看下面的部分,我已经贴出了所以的Java代码,注释也很详尽,可以方便理解,实在不行,还可以点击博客下方的下载链接,直接下载源码运行一下。

全部源码

[java] view plaincopyprint?
  1. public class MainActivity extends FragmentActivity {
  2. /** DrawerLayout */
  3. private DrawerLayout mDrawerLayout;
  4. /** 左边栏菜单 */
  5. private ListView mMenuListView;
  6. /** 右边栏 */
  7. private RelativeLayout right_drawer;
  8. /** 菜单列表 */
  9. private String[] mMenuTitles;
  10. /** Material Design风格 */
  11. private MaterialMenuIcon mMaterialMenuIcon;
  12. /** 菜单打开/关闭状态 */
  13. private boolean isDirection_left = false;
  14. /** 右边栏打开/关闭状态 */
  15. private boolean isDirection_right = false;
  16. private View showView;
  17. @Override
  18. protected void onCreate(Bundle savedInstanceState) {
  19. super.onCreate(savedInstanceState);
  20. setContentView(R.layout.activity_main);
  21. mDrawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
  22. mMenuListView = (ListView) findViewById(R.id.left_drawer);
  23. right_drawer = (RelativeLayout) findViewById(R.id.right_drawer);
  24. this.showView = mMenuListView;
  25. // 初始化菜单列表
  26. mMenuTitles = getResources().getStringArray(R.array.menu_array);
  27. mMenuListView.setAdapter(new ArrayAdapter<String>(this,
  28. R.layout.drawer_list_item, mMenuTitles));
  29. mMenuListView.setOnItemClickListener(new DrawerItemClickListener());
  30. // 设置抽屉打开时,主要内容区被自定义阴影覆盖
  31. mDrawerLayout.setDrawerShadow(R.drawable.drawer_shadow,
  32. GravityCompat.START);
  33. // 设置ActionBar可见,并且切换菜单和内容视图
  34. getActionBar().setDisplayHomeAsUpEnabled(true);
  35. getActionBar().setHomeButtonEnabled(true);
  36. mMaterialMenuIcon = new MaterialMenuIcon(this, Color.WHITE, Stroke.THIN);
  37. mDrawerLayout.setDrawerListener(new DrawerLayoutStateListener());
  38. if (savedInstanceState == null) {
  39. selectItem(0);
  40. }
  41. }
  42. /**
  43. * ListView上的Item点击事件
  44. *
  45. */
  46. private class DrawerItemClickListener implements
  47. ListView.OnItemClickListener {
  48. @Override
  49. public void onItemClick(AdapterView<?> parent, View view, int position,
  50. long id) {
  51. selectItem(position);
  52. }
  53. }
  54. /**
  55. * DrawerLayout状态变化监听
  56. */
  57. private class DrawerLayoutStateListener extends
  58. DrawerLayout.SimpleDrawerListener {
  59. /**
  60. * 当导航菜单滑动的时候被执行
  61. */
  62. @Override
  63. public void onDrawerSlide(View drawerView, float slideOffset) {
  64. showView = drawerView;
  65. if (drawerView == mMenuListView) {// 根据isDirection_left决定执行动画
  66. mMaterialMenuIcon.setTransformationOffset(
  67. MaterialMenuDrawable.AnimationState.BURGER_ARROW,
  68. isDirection_left ? 2 - slideOffset : slideOffset);
  69. } else if (drawerView == right_drawer) {// 根据isDirection_right决定执行动画
  70. mMaterialMenuIcon.setTransformationOffset(
  71. MaterialMenuDrawable.AnimationState.BURGER_ARROW,
  72. isDirection_right ? 2 - slideOffset : slideOffset);
  73. }
  74. }
  75. /**
  76. * 当导航菜单打开时执行
  77. */
  78. @Override
  79. public void onDrawerOpened(android.view.View drawerView) {
  80. if (drawerView == mMenuListView) {
  81. isDirection_left = true;
  82. } else if (drawerView == right_drawer) {
  83. isDirection_right = true;
  84. }
  85. }
  86. /**
  87. * 当导航菜单关闭时执行
  88. */
  89. @Override
  90. public void onDrawerClosed(android.view.View drawerView) {
  91. if (drawerView == mMenuListView) {
  92. isDirection_left = false;
  93. } else if (drawerView == right_drawer) {
  94. isDirection_right = false;
  95. showView = mMenuListView;
  96. }
  97. }
  98. }
  99. /**
  100. * 切换主视图区域的Fragment
  101. *
  102. * @param position
  103. */
  104. private void selectItem(int position) {
  105. Fragment fragment = new ContentFragment();
  106. Bundle args = new Bundle();
  107. switch (position) {
  108. case 0:
  109. args.putString("key", mMenuTitles[position]);
  110. break;
  111. case 1:
  112. args.putString("key", mMenuTitles[position]);
  113. break;
  114. case 2:
  115. args.putString("key", mMenuTitles[position]);
  116. break;
  117. case 3:
  118. args.putString("key", mMenuTitles[position]);
  119. break;
  120. default:
  121. break;
  122. }
  123. fragment.setArguments(args); // FragmentActivity将点击的菜单列表标题传递给Fragment
  124. FragmentManager fragmentManager = getSupportFragmentManager();
  125. fragmentManager.beginTransaction()
  126. .replace(R.id.content_frame, fragment).commit();
  127. // 更新选择后的item和title,然后关闭菜单
  128. mMenuListView.setItemChecked(position, true);
  129. setTitle(mMenuTitles[position]);
  130. mDrawerLayout.closeDrawer(mMenuListView);
  131. }
  132. /**
  133. * 点击ActionBar上菜单
  134. */
  135. @Override
  136. public boolean onOptionsItemSelected(MenuItem item) {
  137. int id = item.getItemId();
  138. switch (id) {
  139. case android.R.id.home:
  140. if (showView == mMenuListView) {
  141. if (!isDirection_left) { // 左边栏菜单关闭时,打开
  142. mDrawerLayout.openDrawer(mMenuListView);
  143. } else {// 左边栏菜单打开时,关闭
  144. mDrawerLayout.closeDrawer(mMenuListView);
  145. }
  146. } else if (showView == right_drawer) {
  147. if (!isDirection_right) {// 右边栏关闭时,打开
  148. mDrawerLayout.openDrawer(right_drawer);
  149. } else {// 右边栏打开时,关闭
  150. mDrawerLayout.closeDrawer(right_drawer);
  151. }
  152. }
  153. break;
  154. case R.id.action_personal:
  155. if (!isDirection_right) {// 右边栏关闭时,打开
  156. if (showView == mMenuListView) {
  157. mDrawerLayout.closeDrawer(mMenuListView);
  158. }
  159. mDrawerLayout.openDrawer(right_drawer);
  160. } else {// 右边栏打开时,关闭
  161. mDrawerLayout.closeDrawer(right_drawer);
  162. }
  163. break;
  164. default:
  165. break;
  166. }
  167. return super.onOptionsItemSelected(item);
  168. }
  169. /**
  170. * 根据onPostCreate回调的状态,还原对应的icon state
  171. */
  172. @Override
  173. protected void onPostCreate(Bundle savedInstanceState) {
  174. super.onPostCreate(savedInstanceState);
  175. mMaterialMenuIcon.syncState(savedInstanceState);
  176. }
  177. /**
  178. * 根据onSaveInstanceState回调的状态,保存当前icon state
  179. */
  180. @Override
  181. protected void onSaveInstanceState(Bundle outState) {
  182. mMaterialMenuIcon.onSaveInstanceState(outState);
  183. super.onSaveInstanceState(outState);
  184. }
  185. /**
  186. * 加载菜单
  187. */
  188. @Override
  189. public boolean onCreateOptionsMenu(Menu menu) {
  190. // Inflate the menu; this adds items to the action bar if it is present.
  191. getMenuInflater().inflate(R.menu.main, menu);
  192. return true;
  193. }
  194. }

源码请在这里下载

Android组件——使用DrawerLayout仿网易新闻v4.4侧滑菜单相关推荐

  1. android 酷狗demo_Android仿酷狗音乐自定义侧滑菜单控件简单实现

    随着Android的不断成熟,许多绚丽的效果也在不断的被大家开发出来,其中侧滑的效果用到的项目很多,用的好的更是给吸引了很多用户.国内像QQ和酷狗App的侧滑就很给力,所以查了一些资料,并结合View ...

  2. Android 开源框架ViewPageIndicator 和 ViewPager 仿网易新闻客户端Tab标签

     转载请注明出处:http://blog.csdn.net/xiaanming/article/details/10766053 之前用JakeWharton的开源框架ActionBarSherl ...

  3. Android高仿网易新闻客户端之动态添加标签

    承接上一篇文章:Android高仿网易新闻客户端之首页,今天来实现动态添加标签效果. 动态标签页是一个流式布局,实现了宽度自动换行高度自动分配的功能,代码如下: FlowLayout.java pac ...

  4. android分类功能,Android 仿网易新闻客户端分类排序功能

    先来看看网易新闻客户端以及自己实现的效果图,效果当然还是网易的好 gridviewsort.gif 如何实现拖拽一个Item 用WindowManager添加一个ImageView,并且将这个Imag ...

  5. android 仿网易标签切换,Android 仿网易新闻客户端Tab标签

    Android 开源框架ViewPageIndicator和ViewPager仿网易新闻客户端Tab标签 http://blog.csdn.net/xiaanming/article/details/ ...

  6. android 仿网易新闻客户端源码都有

    原文:android 仿网易新闻客户端源码都有 android 仿网易新闻服务端源码 源代码下载地址: http://www.zuidaima.com/share/1550463560944640.h ...

  7. 仿网易新闻的页面(ViewPager作为RecyclerView的Header)

    需求 > 想实现一个仿网易新闻的页面,上面是轮播的图片,下面是 RecyclerView 显示新闻列表. 本文链接 http://blog.csdn.net/never_cxb/article/ ...

  8. android 抽屉组件,Android组件之DrawerLayout实现抽屉菜单

    DrawerLayout组件同样是V4包中的组件,也是直接继承于ViewGroup类,所以这个类也是一个容器类. 抽屉菜单的摆放和布局通过android:layout_gravity属性来控制,可选值 ...

  9. 仿网易新闻客户端的上面的tab和下面的功能条

    2019独角兽企业重金招聘Python工程师标准>>> 仿网易新闻客户端的上面的tab和下面的功能条 package com.and.netease; import com.and. ...

最新文章

  1. 移动端访问mysql_java – (可能)数百个移动客户端访问MySQL数据库的最佳方法是什么?...
  2. 《研磨设计模式》chap3 外观模式Facade
  3. esp8266 php 接口,ESP8266_SDK基础(5)智能插座_完整项目代码
  4. Linux 命令之 unzip -- 解压缩文件
  5. html上拉下拉查看文字内容,html5上拉下拉事件效果演示
  6. 阿里推出“阿里云网盘”App;Linux 发布 29 周年​| 极客头条
  7. 几个常用的Oracle函数及实例运用
  8. bit是python最快的bitcoin库_新的Bitcoinpython节点比以前的Python库快100倍
  9. linux 注册并配置
  10. sqlserver查询语句实例
  11. 传输层协议、应用层协议
  12. LeetCode—面试题:移除重复节点(哈希集合)
  13. 怎么在word和python中输入对号
  14. Pytorch中torch.nn.DataParallel负载均衡问题
  15. 理科爱好者杂志理科爱好者杂志社理科爱好者编辑部2022年第3期目录
  16. 克隆一个自己的 AI 来上网课,
  17. 微信认证300元发票获取
  18. windows挂载webdav
  19. ZYNQ基本用法------DDR(1)
  20. 英雄杀朱雀之章在线活动

热门文章

  1. 论逻辑思维和理解能力对程序员的重要性
  2. 提升HTML5的性能体验系列之一 避免切页白屏
  3. 二维码原理与编码介绍
  4. GBase 8a的产品简介
  5. Windows API 编程起始——创建一个窗口
  6. canvas标签设置长宽
  7. border-radius的使用
  8. 关于GPL协议的理解(开源与商用、免费与收费的理解)
  9. dataguard日常管理
  10. 雷军:人因梦想而伟大 金山骨子里重视技术尊重程序员