Android高级UI开发(九)之侧滑菜单 --抽屉

举报
yd_57386892 发表于 2020/12/29 00:29:28 2020/12/29
4k+ 1 0
【摘要】 Android里的抽屉控件在Android2.0---Android2.3是最常见的,记得当时Android系统的桌面本身就自带一个抽屉控件,点击它则展开所有已安装的应用。直到Android4.0问世后比较流行的就是侧滑了,例如新浪新闻APP。实现侧滑的方法比较多,今天我们先讲第一种方法,那就是使用抽屉控件DrawerLayout来实现侧滑菜单,具体效果如下图: ...

Android里的抽屉控件在Android2.0---Android2.3是最常见的,记得当时Android系统的桌面本身就自带一个抽屉控件,点击它则展开所有已安装的应用。直到Android4.0问世后比较流行的就是侧滑了,例如新浪新闻APP。实现侧滑的方法比较多,今天我们先讲第一种方法,那就是使用抽屉控件DrawerLayout来实现侧滑菜单,具体效果如下图:

1. 首先,我们来看一下布局XML文件


      <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
      android:id="@+id/drawerlayout"
      android:layout_width="match_parent"
      android:layout_height="match_parent">
      <!-- 内容部分的布局 -->
      <LinearLayout
      android:layout_width="fill_parent"
      android:layout_height="fill_parent"
      android:orientation="vertical" >
      <android.support.v7.widget.Toolbar
      android:id="@+id/toolbar"
      android:layout_width="fill_parent"
      android:layout_height="wrap_content"
      android:background="?attr/colorPrimary" />
      <TextView
      android:textColor="#ffffff"
      android:layout_width="match_parent"
      android:layout_height="match_parent"
      android:background="#000000"
      android:text="内容" />
      </LinearLayout>
      <!-- 侧滑菜单左侧部分 -->
      <LinearLayout
      android:layout_width="200dp"
      android:layout_height="fill_parent"
      android:layout_gravity="start"
      android:orientation="vertical"
      android:paddingTop="50dp" >
      <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="列表项1" />
      <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="列表项2" />
      <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="列表项3" />
      </LinearLayout>
      <!-- 侧滑菜单右侧部分 -->
      <LinearLayout
      android:layout_width="200dp"
      android:layout_height="fill_parent"
      android:layout_gravity="end"
      android:background="#ff0000"
      android:orientation="vertical"
      android:paddingTop="50dp" >
      <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="item1" />
      <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="item2" />
      <TextView
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:text="item3" />
      </LinearLayout>
      </android.support.v4.widget.DrawerLayout>
  
 

这个XML布局的根布局是DrawerLayout抽屉控件,子控件实质包含了两部分,第一部分是内容,第二部分是侧滑菜单的布局。

我们先看这里的第一部分:内容布局,它是由一个包含一个TOOLBAR(Android标题栏)控件 与 一个TextView。再来看第二部分:这里有2个LinearLayout,其中第一个的属性 android:layout_gravity = "start",另一个android:layout_gravity="end",分别表示屏幕左边的侧滑菜单与屏幕右边的侧滑菜单。好了,通过分析我们这个Demo工程的界面有2个侧滑菜单与一个显示主体内容的页面。

2.  MainActivity代码:

主要加载1中的布局UI,并控制侧滑菜单与内容页面的缩放大小及位移等动画属性。 


      package com.anyikang.volunteer.sos.swipemenulist;
      import android.os.Bundle;
      import android.support.v4.widget.DrawerLayout;
      import android.support.v7.app.ActionBarDrawerToggle;
      import android.support.v7.app.AppCompatActivity;
      import android.support.v7.widget.Toolbar;
      import android.util.Log;
      import android.view.View;
      public class MainActivity extends AppCompatActivity {
      private Toolbar toolbar;
      private DrawerLayout drawerlayout;
      private String TAG = "MainActivity";
      @Override
      protected void onCreate(Bundle savedInstanceState) {
      super.onCreate(savedInstanceState);
       setContentView(R.layout.activity_main);
       toolbar = (Toolbar)findViewById(R.id.toolbar);
      // gxw- setSupportActionBar(toolbar);
       drawerlayout = (DrawerLayout)findViewById(R.id.drawerlayout);
       ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(
      this, drawerlayout, toolbar,
       R.string.drawer_open, R.string.drawer_close);
      //同步drawerToggle按钮与侧滑菜单的打开(关闭)状态
       drawerToggle.syncState();
      //侧滑菜单与drawerToggle绑在一起,drawerToggle按钮点击打开(关闭)侧滑菜单
      // drawerlayout.setDrawerListener(drawerToggle);
       drawerlayout.setDrawerListener(new DrawerLayout.DrawerListener() {
      @Override
      public void onDrawerStateChanged(int newState) {
      // 打开关闭状态切换时调用
       }
      @Override
      public void onDrawerSlide(View drawerView, float slideOffset) {
      // 滑动的过程中执行 slideOffset:0~1
       View content = drawerlayout.getChildAt(0);
       View menu = drawerView;
      float scale = 1-slideOffset;//1~0
      float leftScale = (float) (1-0.3*scale);
      float rightScale = (float) (0.7f+0.3*scale);//0.7~1
       menu.setScaleX(leftScale);//1~0.7
       menu.setScaleY(leftScale);//1~0.7
       content.setScaleX(rightScale);
       content.setScaleY(rightScale);
       content.setTranslationX(menu.getMeasuredWidth()*slideOffset);//0~width
       Log.i(TAG,"slideOffset="+slideOffset+",leftScale="+leftScale+",rightScale="+rightScale);
       }
      @Override
      public void onDrawerOpened(View drawerView) {
      // 打开了菜单
       }
      @Override
      public void onDrawerClosed(View drawerView) {
      // 关闭了菜单
       }
       });
       }
      }
  
 

 我们主要来分析以下两段代码:

第一段,


        ActionBarDrawerToggle drawerToggle = new ActionBarDrawerToggle(
      this, drawerlayout, toolbar,
       R.string.drawer_open, R.string.drawer_close);
      //同步状态
       drawerToggle.syncState();
  
 

这段代码的作用是将TOOLBAR标题栏左上角的返回按钮(向导按钮)与 抽屉控件drawerlayout关联起来,(1)如果当前侧滑菜单已显示,那么当点击“向导按钮”时,将控制drawerlayout抽屉关闭,即达到了隐藏侧滑菜单的目的;(2)同理,当前侧滑菜单已隐藏,那么当点击“向导按钮”时,将控制drawerlayout抽屉打开,即达到了展示侧滑菜单的目的;然而,想要正确的实现上述(1)(2)动作,前提是需要调用drawToggle.syncState()将抽屉的状态(当前是打开还是关闭)与“向导按钮”的状态同步,即抽屉打开时,“向导按钮”状态也应该处于打开状态,这样才能实现再次点击“向导按钮”时抽屉控件应该表现关闭抽屉的动作。

第二段,


       drawerlayout.setDrawerListener(new DrawerLayout.DrawerListener() {
      @Override
      public void onDrawerStateChanged(int newState) {
      // 打开关闭状态切换时调用
       }
      @Override
      public void onDrawerSlide(View drawerView, float slideOffset) {
      // 滑动过程中调用 slideOffset:0~1
       View content = drawerlayout.getChildAt(0);
       View menu = drawerView;
      float scale = 1-slideOffset;//1~0
      float leftScale = (float) (1-0.3*scale); //0.7~1
      float rightScale = (float) (0.7f+0.3*scale);//1~0.7
       menu.setScaleX(leftScale);//0.7~1
       menu.setScaleY(leftScale);//0.7~1
       content.setScaleX(rightScale); //1~0.7
       content.setScaleY(rightScale); //1~0.7
       content.setTranslationX(menu.getMeasuredWidth()*(slideOffset));//0~width
       Log.i(TAG,"slideOffset="+slideOffset+",leftScale="+leftScale+",rightScale="+rightScale);
       }
      @Override
      public void onDrawerOpened(View drawerView) {
      // 打开了侧滑菜单
       }
      @Override
      public void onDrawerClosed(View drawerView) {
      // 关闭了侧滑菜单
       }
       });
  
 

         这里使用serDrawerListener来监听抽屉控件drawerlayout的动作行为,我们主要来看中间这个函数onDrawerSlide,它包含了一个参数slideOffset,这个参数代表了抽屉控件滑出的百分比(也就是侧滑菜单滑出的百分比),例如现在的左边侧滑菜单是隐藏的,然后我们滑动屏幕左边缘,侧滑菜单会跟着滑动出来,当我们观察到当slideOffset这个值为0.8时,侧滑菜单界面的80%已经展示出来,另外20%的界面仍隐藏在屏幕左侧以外。这说明slideOffset并不是侧滑菜单移动过的像素距离,而是移动过的像素距离dx 占 侧滑菜单整体宽度的一个百分比,它的值是由0-1,即0%-100%,简单的讲就是整个侧滑菜单宽度漏出来的百分比 。

        明白了slideOffset的含义后,我们来分析我们的代码,举个例子,当从屏幕左侧滑出菜单时,slideOffset从0变为1,这时scale的值由1变为0,leftScale的值由0.7变为1。menu.setScaleX, menu.setScaleY会使侧滑菜单的大小先缩放为原来的70%,然后逐渐扩大到原本的大小,即菜单完整展示出来,与此同时content.setTranslationX逐渐位移内容布局从0(内容布局的原来左边缘)到侧滑菜单的宽度,content.setScaleX,setScaleY会将内容布局逐渐缩放到原来的70%(由完整大小开始逐渐缩小到70%)。这样就实现了我们侧滑菜单时,菜单由小变大,内容布局由大变小并且随着侧滑菜单的滑出逐渐被推到屏幕的右半部分的效果。

  其余的几个监听函数,我相信大家看到函数名就明白了,在此不再赘述,最后按照惯例给出源码下载地址:

https://download.csdn.net/download/gaoxiaoweiandy/10590696

文章来源: blog.csdn.net,作者:冉航--小虾米,版权归原作者所有,如需转载,请联系作者。

原文链接:blog.csdn.net/gaoxiaoweiandy/article/details/81505914

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

作者其他文章

评论(1

抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。