Android高级进阶(九)之侧滑菜单 --抽屉

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/gaoxiaoweiandy/article/details/81505914