两种方式实现Android侧滑菜单

侧滑菜单的两种实现

  1. 使用DrawerLayout,灵活度比较高。
  2. 使用DrawerLayout+NavigationView,这是谷歌对Material Design的一种标准化。

使用DrawerLayout实现侧滑

首先,我们需要一个布局:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <android.support.v7.widget.Toolbar
        android:id="@+id/toolbar"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#D197F2"
        app:title="标题"
        app:titleTextColor="#fff"/>

    <android.support.v4.widget.DrawerLayout
        android:id="@+id/drawer"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:orientation="vertical">

            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="内容"/>

        </LinearLayout>

        <LinearLayout
            android:layout_width="200dp"
            android:layout_height="match_parent"
            android:layout_gravity="start"
            android:background="@android:color/holo_blue_light"
            android:orientation="vertical">

            <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>
    </android.support.v4.widget.DrawerLayout>
</LinearLayout>


这个布局侧滑菜单包括了菜单部分以及内容部分,用DrawerLayout来包裹起来。其中,菜单部分的根布局需要添加android:layout_gravity="start",如果是右滑的话,改为end即可。这样就可以完成了一个基本的侧滑效果。

DrawerLayout的实现其实是通过ViewDragHelper来实现的,DrawerLayout构造函数的相关代码如下:

public DrawerLayout(Context context, AttributeSet attrs, int defStyle) {
    super(context, attrs, defStyle);

    mLeftCallback = new ViewDragCallback(Gravity.LEFT);
    mRightCallback = new ViewDragCallback(Gravity.RIGHT);

    mLeftDragger = ViewDragHelper.create(this, TOUCH_SLOP_SENSITIVITY, mLeftCallback);
    mLeftDragger.setEdgeTrackingEnabled(ViewDragHelper.EDGE_LEFT);
    mLeftDragger.setMinVelocity(minVel);
    mLeftCallback.setDragger(mLeftDragger);
}

利用DrawerLayout的监听实现一些效果
例如,我们可以实现侧滑的时候,Toolbar左上角的按钮实时变化,我们可以添加一个监听ActionBarDrawerToggle:

toolbar = (Toolbar) findViewById(R.id.toolbar);
drawer = (DrawerLayout) findViewById(R.id.drawer);

ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(this, drawer, toolbar, R.string.drawer_open, R.string.drawer_close);
toggle.syncState();

drawer.addDrawerListener(toggle);

下面我们分析一下实现原理:

其中,ActionBarDrawerToggle实现了DrawerLayout.DrawerListener。并且在滑动的过程中不断 刷新左上角的Drawerable:

@Override
public void onDrawerSlide(View drawerView, float slideOffset) {
    setPosition(Math.min(1f, Math.max(0, slideOffset)));
}
setPosition的实现如下:

private void setPosition(float position) {
    if (position == 1f) {
        mSlider.setVerticalMirror(true);
    } else if (position == 0f) {
        mSlider.setVerticalMirror(false);
    }
    mSlider.setProgress(position);
}

其实就是在滑动的过程中不断改变mSlider(一个自定义Drawerable对象)的Progress,从而不断刷新状态。

因此,我们可以做一些自定义的特效,例如侧滑的时候缩放、平移:

drawer.addDrawerListener(new DrawerLayout.DrawerListener() {

    @Override
    public void onDrawerStateChanged(int newState) {
        // 状态发生改变

    }

    @Override
    public void onDrawerSlide(View drawerView, float slideOffset) {
        // 滑动的过程当中不断地回调 slideOffset:0~1
        View content = drawer.getChildAt(0);
        float scale = 1 - slideOffset;//1~0
        float leftScale = (float) (1 - 0.3 * scale);
        float rightScale = (float) (0.7f + 0.3 * scale);//0.7~1
        drawerView.setScaleX(leftScale);//1~0.7
        drawerView.setScaleY(leftScale);//1~0.7

        content.setScaleX(rightScale);
        content.setScaleY(rightScale);
        content.setTranslationX(drawerView.getMeasuredWidth() * (1 - scale));//0~width

    }

    @Override
    public void onDrawerOpened(View drawerView) {
        // 打开
    }

    @Override
    public void onDrawerClosed(View drawerView) {
        // 关闭
    }
});

使用DrawerLayout+NavigationView实现侧滑

同样道理,我们需要一个布局,同样的,用DrawerLayout进行包裹内容以及菜单,其中菜单是一个NavigationView,可以指定头部以及菜单部分,并且提供一些属性的设置。(可以看出来,使用NavigationView的灵活度比较差,如果项目是直接使用这种模板的话,可以直接使用,不然的话我们还是使用一般的方式去实现)

<android.support.v4.widget.DrawerLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/drawer"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- 内容部分 -->
    <FrameLayout
        android:id="@+id/fl"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"/>

    <!-- 菜单部分 -->
    <android.support.design.widget.NavigationView
        android:id="@+id/nav_view"
        android:layout_width="wrap_content"
        android:layout_height="match_parent"
        android:layout_gravity="start"
        app:headerLayout="@layout/navigation_headerlayout"
        app:menu="@menu/navigation_menu"/>

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

这里我们指定了头部如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center_horizontal"
    android:orientation="vertical">

    <ImageView
        android:id="@+id/iv_icon"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_marginTop="20dp"
        android:src="@drawable/icon_people"/>

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:text="test"
        android:textSize="20sp"/>

</LinearLayout>

菜单部分如下(menu文件夹下建立),其中菜单可以嵌套:

<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
    <item
        android:id="@+id/action_gallery"
        android:icon="@android:drawable/ic_menu_gallery"
        android:orderInCategory="100"
        android:title="相册"
        />
    <item
        android:id="@+id/action_details"
        android:icon="@android:drawable/ic_menu_info_details"
        android:orderInCategory="100"
        android:title="详情"
        />
    <item
        android:id="@+id/action_about"
        android:icon="@android:drawable/ic_menu_help"
        android:orderInCategory="100"
        android:title="关于"
        />
    <item
        android:id="@+id/action_music"
        android:icon="@android:drawable/ic_menu_more"
        android:orderInCategory="100"
        android:title="音乐"
        >
        <menu>
            <item
                android:id="@+id/action_play"
                android:icon="@android:drawable/ic_media_play"
                android:title="播放"/>
            <item
                android:id="@+id/action_pause"
                android:icon="@android:drawable/ic_media_pause"
                android:title="暫停"/>
        </menu>
    </item>

</menu>

到现在为止,就可以实现侧滑了,最后我们添加上对应的点击事件,然后关闭菜单:

nav_view = (NavigationView) findViewById(R.id.nav_view);
drawer = (DrawerLayout) findViewById(R.id.drawer);
nav_view.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem item) {
        Toast.makeText(NavigationViewActivity.this, item.getTitle(), Toast.LENGTH_SHORT).show();
        drawer.closeDrawer(nav_view);
        return false;
    }
});

nav_view.getHeaderView(0).findViewById(R.id.iv_icon).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(NavigationViewActivity.this, "点击了头部的图标", Toast.LENGTH_SHORT).show();
        drawer.closeDrawer(nav_view);
    }
});


  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值