前言

这几天正在研究几个比较有名的开源项目,偶然发现了SlidingUpPanelLayout这个神器,经过一番研究,和大家一起分享一下学习心得。 如果要使用滑动菜单,目前最流行的应该是DrawerLayout,这个由谷歌开源的控件已经被放在android包中,使用起来非常的方便,唯一的遗憾是DrawerLayout只支持左右滑动的菜单,但是并不支持上下滑动的菜单,我们今天要介绍的SlidingUpPanelLayout,相当于竖向的DrawerLayout。 首先我们看图:

android adb 滑动后长按不松 android滑动菜单_android 取listview某一行


很多的音乐播放器都有这样的交互, 使用SlidingUpPanelLayout就可以实现。 SlidingUpPanelLayout早在2016年就已经发布了, 肯定已经非常的稳定,大家可以到github上先看看基本的使用方法。https://github.com/umano/AndroidSlidingUpPanel

正文

首先我们需要在build.gradle文件中依赖SlidingUpPanelLayout:


dependencies {    repositories {        mavenCentral()    }    compile 'com.sothree.slidinguppanel:library:3.4.0'}

我们写一个最简单的布局:

<?xml version="1.0" encoding="utf-8"?>            xmlns:app="http://schemas.android.com/apk/res-auto"        xmlns:tools="http://schemas.android.com/tools"        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical"        tools:context=".MainActivity">                    android:id="@+id/button"            android:layout_width="match_parent"            android:text="button"            android:layout_height="wrap_content"/>                    android:id="@+id/slidingUpPanelLayout"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:gravity="bottom"            app:umanoOverlay="true"            app:umanoFadeColor="@color/colorAccent"            app:umanoPanelHeight="95dp">                            android:layout_width="match_parent"                android:layout_height="match_parent"                android:background="@color/colorPrimary"                android:gravity="center"                android:clickable="true"                android:focusable="false"                android:focusableInTouchMode="true"                android:text="content" />                            android:id="@+id/panel"                android:layout_width="match_parent"                android:layout_height="match_parent"                android:orientation="vertical">                                    android:layout_width="match_parent"                    android:layout_height="wrap_content"                    android:ellipsize="end"                    android:gravity="center"                    android:text="@string/content"                    android:textColor="@color/white" />

android adb 滑动后长按不松 android滑动菜单_android 取listview某一行_02


仅仅定义xml,一个可以上滑的菜单就完成了。 接下来我们看看SlidingUpPanelLayout都提供了哪些方法。

setPanelHeight


setPanelHeight对应自定义属性umanoPanelHeight。

当菜单被折叠时,显示的高度


上面的demo中已经使用了这个自定义属性,非常好理解。

setOverlayed


setOverlayed对应自定义属性umanoOverlay。

意思是菜单是否要覆盖到主页面之上:
如果是false,相当于LinearLayout,主页面在上,菜单在下
如果是true,相当于FrameLayout


默认是false类型,具体按照UE的需求自行选择。

setClipPanel


setClipPanel对应自定义属性umanoClipPanel。 是否要裁剪菜单的区域,特别注意, 此属性只会在 Overlayed = false的时候有效 如果是true,会把被菜单遮盖的区域,主页面的内容会被裁掉。

如果是false,菜单的内容和主页面的内容会同时显示,覆盖在上面。

这个属性,我猜测主要是为了优化绘制速度的,如果你的菜单有不透明背景,建议设置为true,缩小主页面绘制的区域范围,提高流畅度。

setDragView


setDragView对应自定义属性umanoDragView。 从字面的意思来看,就是可以拖拽的View,如果你不希望整个菜单都可以被手势展开或折叠,可以设置某一个View作为响应手势的热区。

setParallaxOffset


setParallaxOffset对应自定义属性umanoParallaxOffset。

当菜单在滑动的时候,主页面一起移动的视觉偏差。


例如菜单展开的过程中,主页面向上移动100dp,视觉上有一种主页面被顶上去的效果。

setFadeOnClickListener


setFadeOnClickListener没有对应的自定义属性。 如果你在滑动的过程中,点击了菜单以外的部分, 你会发现菜单的展开或折叠动画被中断了, 如果你希望在点击的时候做什么处理, 你可以设置setFadeOnClickListener。 不过此处有坑,那就是你的主页面必须是可点的, 以刚才的demo为例:

android:layout_width="match_parent"                android:layout_height="match_parent"                android:background="@color/colorPrimary"                android:gravity="center"                android:clickable="true"                android:focusable="false"                android:focusableInTouchMode="true"                android:text="content" />


我设置的主页面只是一个TextView, TextView默认是不可点击的, 所以无论怎么点setFadeOnClickListener都不会触发, 所以需要手动加上android:clickable=true, 才会响应setFadeOnClickListener。

setCoveredFadeColor


setCoveredFadeColor对应自定义属性umanoFadeColor。

菜单覆盖在主页面上的背景颜色,此颜色可以被rootView的背景颜色盖住,也可以理解为阴影的颜色

setAnchorPoint

setAnchorPoint对应自定义属性umanoAnchorPoint。

自定义的菜单展开的锚点比例。值为0-1之间的小数,非手动拖拽菜单的情况下(例如点击)只会展开到这个锚点的比例。

例如,setAnchorPoint(0.5f),菜单只会自动展开一半。


setPanelState

设置菜单的展开状态,目前主要有:


public enum PanelState {        EXPANDED,  // 展开        COLLAPSED,   // 折叠        ANCHORED,    // 锚点        HIDDEN,         // 隐藏        DRAGGING    // 拖拽中(个人觉得理解为变化中更合适)    }


与之相关属性有umanoInitialState:菜单的初始状态。

setScrollableView


setScrollableView对应的自定义属性为umanoScrollableView。

可以滚动的Child。如果内部有ScrollView,ListView,RecyclerView,通过这个方法,会把手势的滑动让给他们,从而避免SlidingUpPanelLayout和child之间的手势冲突。


SlidingUpPanelLayout只能设置一个child作为ScrollableView。

setScrollableViewHelper


setScrollableViewHelper没有对应的自定义属性。 他的作用和setScrollableView类似, 只不过setScrollableViewHelper更具有通用性, 可以对的每一个View自定义手势处理:

public int getScrollableViewScrollPosition(View scrollableView, boolean isSlidingUp) {        if (scrollableView == null) return 0;        if (scrollableView instanceof ScrollView) {            ...        } else if (scrollableView instanceof ListView && ((ListView) scrollableView).getChildCount() > 0) {            ...        } else if (scrollableView instanceof RecyclerView && ((RecyclerView) scrollableView).getChildCount() > 0) {            ....        } else {            return 0;        }    }


ScrollableViewHelper内部已经处理了 ScrollView,ListView,RecyclerView, 能够满足大部分的需求。

addPanelSlideListener


addPanelSlideListener是SlidingUpPanelLayout最核心的api, 监听菜单展开的进度。他的用法和动画的的监听基本一样:

SlidingUpPanelLayout.PanelSlideListener {            override fun onPanelSlide(panel: View?, slideOffset: Float) {                    // panel :就是菜单的根布局                    // slideOffset:菜单展开的比例,值为0到1,0为折叠状态,1为展开状态            }            override fun onPanelStateChanged(                panel: View?,                previousState: SlidingUpPanelLayout.PanelState?,                newState: SlidingUpPanelLayout.PanelState?            ) {                // newState:目前SlidingUpPanelLayout的状态            }        }

EXPANDED,  // 展开
COLLAPSED,   // 折叠
ANCHORED,    // 锚点,这个状态只有设置了锚点才会有
HIDDEN,         // 隐藏
DRAGGING    // 拖拽中(个人觉得理解为变化中更合适),无论是点击还是拖拽,只要是菜单在滑动,都会进入这个状态。


总结


关于SlidingUpPanelLayout的所有内容到此结束了, 几乎所有的api我们都已经介绍了,但是具体的效果建议大家自己去尝试, 尤其是ClipPanel和Overlayed 到这里就结束啦。