SlidingUpPanelLayout:可以上下滑动的菜单布

前言

这几天正在研究几个比较有名的开源项目,偶然发现了SlidingUpPanelLayout这个神器,经过一番研究,和大家一起分享一下学习心得。

如果要使用滑动菜单,目前最流行的应该是DrawerLayout,这个由谷歌开源的控件已经被放在android包中,使用起来非常的方便,唯一的遗憾是DrawerLayout只支持左右滑动的菜单,但是并不支持上下滑动的菜单,我们今天要介绍的SlidingUpPanelLayout,相当于竖向的DrawerLayout。

首先我们看一个动画:


在这里插入图片描述

很多的音乐播放器都有这样的交互,使用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"?>
<layout>

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        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">

        <Button
            android:id="@+id/button"
            android:layout_width="match_parent"
            android:text="button"
            android:layout_height="wrap_content"/>

        <com.sothree.slidinguppanel.SlidingUpPanelLayout
            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">

            <TextView
                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" />

            <RelativeLayout
                android:id="@+id/panel"
                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:ellipsize="end"
                    android:gravity="center"
                    android:text="@string/content"
                    android:textColor="@color/white" />
                                
            </RelativeLayout>

        </com.sothree.slidinguppanel.SlidingUpPanelLayout>

    </LinearLayout>
</layout>
在这里插入图片描述

仅仅定义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为例:

    <TextView
                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,有什么问题可以留言讨论。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,012评论 4 359
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,589评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,819评论 0 237
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,652评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,954评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,381评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,687评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,404评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,082评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,355评论 2 241
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,880评论 1 255
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,249评论 2 250
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,864评论 3 232
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,007评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,760评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,394评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,281评论 2 259

推荐阅读更多精彩内容

  • 01 “他们有明亮的眼睛,却拒绝对视; 有正常听力,却不理会呼唤; 有清脆的嗓音,却不歌唱交谈… 他们,是星星的孩...
    兰若荃阅读 896评论 0 4
  • 好多话,忍着,憋着,后来就懒得说了, 好多事情,失望多了,后来就不在意了, 就是这样,在一次一次失望中, 后来,突...
    宝a宝a阅读 56评论 0 0
  • 2017-12-21 姓名:徐祖德 公司:广东思沃精密机械有限公司 230期_利他1组 272期_乐观2组志工 【...
    徐祖德阅读 134评论 0 0
  • 时光时光慢些吧 不要再让他变老了 …… 每次听到《父亲》这首歌的时候总会突然很难过。可能是因为第一次看到MV的时候...
    橙汁的妈妈阅读 345评论 2 2