[关闭]
@coder-pig 2015-10-09T14:54:56.000000Z 字数 12531 阅读 2022

Android基础入门教程——2.4.15 DrawerLayout(官方侧滑菜单)的简单使用

Android基础入门教程


本节引言:

本节给大家带来基础UI控件部分的最后一个控件:DrawerLayout,官方给我们提供的一个侧滑菜单
控件,和上一节的ViewPager一样,3.0以后引入,低版本使用它,需要v4兼容包,说到侧滑,相信
很多人都用过github上的SlidingMenu,不过好像有两个版本,一个是单独的,另一个需要依赖另一
个开源项目:ActionBarSherlock;既然Google为我们提供了这个控件,为何不用咧,而且在
Material Design设计规范中,随处可见的很多侧滑菜单的动画效果,大都可以通过Toolbar +
DrawerLayout来实现~,本节我们就来探究下这个DrawerLayout的一个基本用法~还有人喜欢把他
称为抽屉控件~官方文档:DrawerLayout


1.使用的注意事项

  • 1.主内容视图一定要是DrawerLayout的第一个子视图
  • 2.主内容视图宽度和高度需要match_parent
  • 3.必须显示指定侧滑视图的android:layout_gravity属性
    android:layout_gravity = "start"时,从左向右滑出菜单
    android:layout_gravity = "end"时,从右向左滑出菜单
    不推荐使用left和right!!!
  • 侧滑视图的宽度以dp为单位,不建议超过320dp(为了总能看到一些主内容视图)
  • 设置侧滑事件:mDrawerLayout.setDrawerListener(DrawerLayout.DrawerListener);
  • 要说一点:可以结合Actionbar使用当用户点击Actionbar上的应用图标,弹出侧滑菜单!
    这里就要通过ActionBarDrawerToggle,它是DrawerLayout.DrawerListener的具体实现类,
    我们可以重写ActionBarDrawerToggle的onDrawerOpened()和onDrawerClosed()以监听抽屉拉出
    或隐藏事件!但是这里我们不讲,因为5.0后我们使用的是Toolbar!有兴趣的可以自行查阅相关
    文档!

2.使用代码示例


示例1:单个侧滑菜单的实现

运行效果图

实现关键代码

首先是我们的主布局,注意:最外层要是DrawerLayout哦!!!!

activity_main.xml

  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/ly_content"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent" />
  9. <ListView
  10. android:id="@+id/list_left_drawer"
  11. android:layout_width="180dp"
  12. android:layout_height="match_parent"
  13. android:layout_gravity="start"
  14. android:background="#080808"
  15. android:choiceMode="singleChoice"
  16. android:divider="#FFFFFF"
  17. android:dividerHeight="1dp" />
  18. </android.support.v4.widget.DrawerLayout>

接着ListView的布局代码和domain类:Item比较简单,就不给出了,直接上中间Fragment的
布局以及代码吧!另外Adapter直接复用我们之前写的那个可复用的MyAdapter!

fg_content.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical">
  6. <TextView
  7. android:id="@+id/tv_content"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:layout_centerInParent="true"
  11. android:textSize="25sp" />
  12. </RelativeLayout>

ContentFragment.java

  1. /**
  2. * Created by Jay on 2015/10/8 0008.
  3. */
  4. public class ContentFragment extends Fragment {
  5. private TextView tv_content;
  6. @Override
  7. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  8. View view = inflater.inflate(R.layout.fg_content, container, false);
  9. tv_content = (TextView) view.findViewById(R.id.tv_content);
  10. String text = getArguments().getString("text");
  11. tv_content.setText(text);
  12. return view;
  13. }
  14. }

最后是我们的Activity类

MainActivity.java

  1. public class MainActivity extends AppCompatActivity implements AdapterView.OnItemClickListener{
  2. private DrawerLayout drawer_layout;
  3. private ListView list_left_drawer;
  4. private ArrayList<Item> menuLists;
  5. private MyAdapter<Item> myAdapter = null;
  6. @Override
  7. protected void onCreate(Bundle savedInstanceState) {
  8. super.onCreate(savedInstanceState);
  9. setContentView(R.layout.activity_main);
  10. drawer_layout = (DrawerLayout) findViewById(R.id.drawer_layout);
  11. list_left_drawer = (ListView) findViewById(R.id.list_left_drawer);
  12. menuLists = new ArrayList<Item>();
  13. menuLists.add(new Item(R.mipmap.iv_menu_realtime,"实时信息"));
  14. menuLists.add(new Item(R.mipmap.iv_menu_alert,"提醒通知"));
  15. menuLists.add(new Item(R.mipmap.iv_menu_trace,"活动路线"));
  16. menuLists.add(new Item(R.mipmap.iv_menu_settings,"相关设置"));
  17. myAdapter = new MyAdapter<Item>(menuLists,R.layout.item_list) {
  18. @Override
  19. public void bindView(ViewHolder holder, Item obj) {
  20. holder.setImageResource(R.id.img_icon,obj.getIconId());
  21. holder.setText(R.id.txt_content, obj.getIconName());
  22. }
  23. };
  24. list_left_drawer.setAdapter(myAdapter);
  25. list_left_drawer.setOnItemClickListener(this);
  26. }
  27. @Override
  28. public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
  29. ContentFragment contentFragment = new ContentFragment();
  30. Bundle args = new Bundle();
  31. args.putString("text", menuLists.get(position).getIconName());
  32. contentFragment.setArguments(args);
  33. FragmentManager fm = getSupportFragmentManager();
  34. fm.beginTransaction().replace(R.id.ly_content,contentFragment).commit();
  35. drawer_layout.closeDrawer(list_left_drawer);
  36. }
  37. }

代码很简单,就不多说了~


示例2.左右两个侧滑菜单的实现

嗯,不知道你有没有发现,从上面的DrawerLayout的布局,我们大概可以猜到,DrawerLayout
最多由三个部分组成,中间的内容部分,左边的侧滑菜单部分,右边的侧滑菜单部分组成!
下面我们来写一个带有两个侧滑菜单的示例!

运行效果图

代码实现

————首先我们创建两个Fragment以及对应的布局,他们分别是左右侧滑菜单!

左边Fragment

布局:fg_left.xml,这里就用了一个图片而以,点击后弹出一个新的Activity;
当然你可以根据自己的需求进行扩展!

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:orientation="vertical" android:layout_width="match_parent"
  4. android:layout_height="match_parent">
  5. <ImageView
  6. android:id="@+id/img_bg"
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. android:background="@mipmap/bg_menu_left"/>
  10. </LinearLayout>

对应的LeftFragment.java

  1. /**
  2. * Created by Jay on 2015/10/9 0009.
  3. */
  4. public class LeftFragment extends Fragment{
  5. private DrawerLayout drawer_layout;
  6. @Override
  7. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  8. View view = inflater.inflate(R.layout.fg_left, container, false);
  9. ImageView img_bg = (ImageView) view.findViewById(R.id.img_bg);
  10. img_bg.setOnClickListener(new View.OnClickListener() {
  11. @Override
  12. public void onClick(View v) {
  13. getActivity().startActivity(new Intent(getActivity(),OtherActivity.class));
  14. drawer_layout.closeDrawer(Gravity.START);
  15. }
  16. });
  17. return view;
  18. }
  19. //暴露给Activity,用于传入DrawerLayout,因为点击后想关掉DrawerLayout
  20. public void setDrawerLayout(DrawerLayout drawer_layout){
  21. this.drawer_layout = drawer_layout;
  22. }
  23. }

右面的Fragment

布局就三个按钮,点击后替换中间部分的Fragment,布局fg_right.xml代码如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:background="#2F9AF2"
  6. android:gravity="center"
  7. android:orientation="vertical">
  8. <Button
  9. android:id="@+id/btn_one"
  10. android:layout_width="wrap_content"
  11. android:layout_height="wrap_content"
  12. android:text="菜单项一" />
  13. <Button
  14. android:id="@+id/btn_two"
  15. android:layout_width="wrap_content"
  16. android:layout_height="wrap_content"
  17. android:text="菜单项二" />
  18. <Button
  19. android:id="@+id/btn_three"
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:text="菜单项三" />
  23. </LinearLayout>

然后对应的是RightFragment.java

  1. /**
  2. * Created by Jay on 2015/10/9 0009.
  3. */
  4. public class RightFragment extends Fragment implements View.OnClickListener{
  5. private DrawerLayout drawer_layout;
  6. private FragmentManager fManager;
  7. @Override
  8. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  9. View view = inflater.inflate(R.layout.fg_right, container, false);
  10. view.findViewById(R.id.btn_one).setOnClickListener(this);
  11. view.findViewById(R.id.btn_two).setOnClickListener(this);
  12. view.findViewById(R.id.btn_three).setOnClickListener(this);
  13. fManager = getActivity().getSupportFragmentManager();
  14. return view;
  15. }
  16. @Override
  17. public void onClick(View v) {
  18. switch (v.getId()){
  19. case R.id.btn_one:
  20. ContentFragment cFragment1 = new ContentFragment("1.点击了右侧菜单项一",R.color.blue);
  21. fManager.beginTransaction().replace(R.id.fly_content,cFragment1).commit();
  22. drawer_layout.closeDrawer(Gravity.END);
  23. break;
  24. case R.id.btn_two:
  25. ContentFragment cFragment2 = new ContentFragment("2.点击了右侧菜单项二",R.color.red);
  26. fManager.beginTransaction().replace(R.id.fly_content,cFragment2).commit();
  27. drawer_layout.closeDrawer(Gravity.END);
  28. break;
  29. case R.id.btn_three:
  30. ContentFragment cFragment3 = new ContentFragment("3.点击了右侧菜单项三",R.color.yellow);
  31. fManager.beginTransaction().replace(R.id.fly_content,cFragment3).commit();
  32. drawer_layout.closeDrawer(Gravity.END);
  33. break;
  34. }
  35. }
  36. public void setDrawerLayout(DrawerLayout drawer_layout){
  37. this.drawer_layout = drawer_layout;
  38. }
  39. }

另外还有一个中间部分填充的ContentFragment,布局:fg_content.xml如下:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="match_parent"
  5. android:orientation="vertical">
  6. <TextView
  7. android:id="@+id/tv_content"
  8. android:layout_width="wrap_content"
  9. android:layout_height="wrap_content"
  10. android:layout_centerInParent="true"
  11. android:textSize="25sp" />
  12. </RelativeLayout>

ContentFragment.java

  1. public class ContentFragment extends Fragment {
  2. private TextView tv_content;
  3. private String strContent;
  4. private int bgColor;
  5. public ContentFragment(String strContent,int bgColor) {
  6. this.strContent = strContent;
  7. this.bgColor = bgColor;
  8. }
  9. @Override
  10. public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
  11. View view = inflater.inflate(R.layout.fg_content, container, false);
  12. view.setBackgroundColor(getResources().getColor(bgColor));
  13. tv_content = (TextView) view.findViewById(R.id.tv_content);
  14. tv_content.setText(strContent);
  15. return view;
  16. }
  17. }

————编写好以后,就到我们的Activity的布局了以及Activity的代码了:
在此之前我们还需要些一个顶部条形栏的布局:

view_topbar.xml

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3. android:layout_width="match_parent"
  4. android:layout_height="wrap_content"
  5. android:background="#DCDEDB">
  6. <Button
  7. android:id="@+id/btn_right"
  8. android:layout_width="40dp"
  9. android:layout_height="40dp"
  10. android:layout_centerVertical="true"
  11. android:layout_alignParentRight="true"
  12. android:background="@drawable/btn_selctor"/>
  13. </RelativeLayout>

然后是activity_main.xml

  1. <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
  2. xmlns:tools="http://schemas.android.com/tools"
  3. android:id="@+id/drawer_layout"
  4. android:layout_width="match_parent"
  5. android:layout_height="match_parent">
  6. <LinearLayout
  7. android:layout_width="match_parent"
  8. android:layout_height="match_parent"
  9. android:orientation="vertical">
  10. <include
  11. android:id="@+id/topbar"
  12. layout="@layout/view_topbar"
  13. android:layout_width="wrap_content"
  14. android:layout_height="48dp" />
  15. <FrameLayout
  16. android:id="@+id/fly_content"
  17. android:layout_width="match_parent"
  18. android:layout_height="match_parent" />
  19. </LinearLayout>
  20. <fragment
  21. android:id="@+id/fg_left_menu"
  22. android:name="jay.com.drawerlayoutdemo2.LeftFragment"
  23. android:layout_width="300dp"
  24. android:layout_height="match_parent"
  25. android:layout_gravity="start"
  26. android:tag="LEFT"
  27. tools:layout="@layout/fg_left" />
  28. <fragment
  29. android:id="@+id/fg_right_menu"
  30. android:name="jay.com.drawerlayoutdemo2.RightFragment"
  31. android:layout_width="100dp"
  32. android:layout_height="match_parent"
  33. android:layout_gravity="end"
  34. android:tag="RIGHT"
  35. tools:layout="@layout/fg_right" />
  36. </android.support.v4.widget.DrawerLayout>

最后是MainActivity.java

  1. public class MainActivity extends AppCompatActivity implements View.OnClickListener {
  2. private DrawerLayout drawer_layout;
  3. private FrameLayout fly_content;
  4. private View topbar;
  5. private Button btn_right;
  6. private RightFragment fg_right_menu;
  7. private LeftFragment fg_left_menu;
  8. private FragmentManager fManager;
  9. @Override
  10. protected void onCreate(Bundle savedInstanceState) {
  11. super.onCreate(savedInstanceState);
  12. setContentView(R.layout.activity_main);
  13. fManager = getSupportFragmentManager();
  14. fg_right_menu = (RightFragment) fManager.findFragmentById(R.id.fg_right_menu);
  15. fg_left_menu = (LeftFragment) fManager.findFragmentById(R.id.fg_left_menu);
  16. initViews();
  17. }
  18. private void initViews() {
  19. drawer_layout = (DrawerLayout) findViewById(R.id.drawer_layout);
  20. fly_content = (FrameLayout) findViewById(R.id.fly_content);
  21. topbar = findViewById(R.id.topbar);
  22. btn_right = (Button) topbar.findViewById(R.id.btn_right);
  23. btn_right.setOnClickListener(this);
  24. //设置右面的侧滑菜单只能通过编程来打开
  25. drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED,
  26. Gravity.END);
  27. drawer_layout.setDrawerListener(new DrawerLayout.DrawerListener() {
  28. @Override
  29. public void onDrawerSlide(View view, float v) {
  30. }
  31. @Override
  32. public void onDrawerOpened(View view) {
  33. }
  34. @Override
  35. public void onDrawerClosed(View view) {
  36. drawer_layout.setDrawerLockMode(
  37. DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.END);
  38. }
  39. @Override
  40. public void onDrawerStateChanged(int i) {
  41. }
  42. });
  43. fg_right_menu.setDrawerLayout(drawer_layout);
  44. fg_left_menu.setDrawerLayout(drawer_layout);
  45. }
  46. @Override
  47. public void onClick(View v) {
  48. drawer_layout.openDrawer(Gravity.RIGHT);
  49. drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED,
  50. Gravity.END); //解除锁定
  51. }
  52. }

好的,至此就大功告成了~,呼呼,下面说下看代码时可能会有的疑惑:

  • 1. drawer_layout.openDrawer(Gravity.END);
    这句是设置打开的哪个菜单START代表左边,END代表右边
  • 2. drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED,Gravity.END);
    锁定右面的侧滑菜单,不能通过手势关闭或者打开,只能通过代码打开!即调用openDrawer方法!
    接着 drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED,Gravity.END);
    解除锁定状态,即可以通过手势关闭侧滑菜单
    最后在drawer关闭的时候调用:
    drawer_layout.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED, Gravity.END);
    再次锁定右边的侧滑菜单!
  • 3. 布局代码中的Tag属性的作用?
    答:这里没用到,在重写DrawerListener的onDrawerSlide方法时,我们可以通过他的第一个
    参数drawerView,调用drawerView.getTag().equals("START")判断触发菜单事件的是哪个
    菜单!然后可以进行对应的操作!

3.代码示例下载

DrawerLayoutDemo.zip
DrawerLayoutDemo2.zip


本节小结:

好的,本节给大家介绍了官方的侧滑控件DrawerLayout的基本用法,使用起来非常的方便!
当然这里仅仅是简单的使用演示,另外看到弘扬大神写过一篇:
Android DrawerLayout 高仿QQ5.2双向侧滑菜单
有兴趣可以看看,如果看完本节的内容,相信你看起来不会怎么吃力~好的!
本节就到这里,跟UI控件这一章说拜拜了~下一章我们开始绘图与动画了,
为我们进阶部分的自定义控件系列打基础!

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注