Android应用Design Support Library完全使用实例

1 背景

上周一年一度的Google IO全球开发者大会刚刚结束,Google在Android这块除过一些优化没有太大亮点。在Android Developer和Android Developer Blog上看了下相关介绍,Google升级了新的Support Library。所以在这里我们就来率先体验一把吧(这篇文章再草稿箱呆了三四天了。。。。终于有时间让她见天日了)。

先看一下Demo演示效果图,完全使用了Google IO 2015的Design Support Library的控件进行代码编写。如下:

这里写图片描述

下载Demo请点击:Design Support Library Demo

2 Design Support Library使用介绍

2-1 综述

支持Android 2.1以上设备。

Gradle build script dependency:

compile 'com.android.support:design:22.2.0' //可修改版本号为自己匹配

Design Support Library包含8个控件,具体如下:

Widget NameDescription
android.support.design.widget.TextInputLayout强大带提示的MD风格的EditText
android.support.design.widget.FloatingActionButtonMD风格的圆形按钮,来自于ImageView
android.support.design.widget.Snackbar类似Toast,添加了简单的单个Action
android.support.design.widget.TabLayout选项卡
android.support.design.widget.NavigationViewDrawerLayout的SlideMenu
android.support.design.widget.CoordinatorLayout超级FrameLayout
android.support.design.widget.AppBarLayoutMD风格的滑动Layout
android.support.design.widget.CollapsingToolbarLayout可折叠MD风格ToolbarLayout

下面详细说说这些控件的特性和使用注意项。

2-2 TextInputLayout控件

这里写图片描述

在MD中,使用TextInputLayout将EditText进行了封装,提示信息会变成一个显示在EditText之上的floating label,这样用户就始终知道他们现在输入的是什么,而且过度动画是平滑的。还可以在下方通过setError设置Error提示,使用比较简单,所以不做过多说明,详情见Demo源码。

注意项:

TextInputLayout中至少嵌套一个EditText。

2-3 FloatingActionButton控件

这里写图片描述

一个负责显示界面基本操作的圆形按钮。Design library中的FloatingActionButton 实现了一个默认颜色为主题中colorAccent的悬浮操作按钮。除了一般大小的悬浮操作按钮,它还支持mini size(fabSize=”mini”)。FloatingActionButton继承自ImageView,你可以使用android:src或者 ImageView的任意方法,比如setImageDrawable()来设置FloatingActionButton里面的图标。

无特别注意项,和普通控件类似。

2-4 Snackbar控件

这里写图片描述

Snackbar为一个操作提供轻量级、快速的反馈。Snackbar显示在屏幕的底部(有MD动画效果浮现和消失),包含了文字信息与一个可选的操作按钮。在指定时间结束之后自动消失。另外,用户还可以在超时之前将它滑动删除。Snackbar被看作是比Toast更强大的快速反馈机制,你会发现他们的API非常相似。你应该注意到了make()方法中把一个View作为第一个参数(Snackbar试图找到一个合适的父亲以确保自己是被放置于底部)。

无特殊注意项,和Toast类似。

2-5 TabLayout控件

这里写图片描述

通过选项卡的方式切换View并不是MD中才有的新概念,它们和顶层导航模式或者组织app中不同分组内容(比如,不同风格的音乐)是同一个概念。 Design library的TabLayout 既实现了固定的选项卡(View的宽度平均分配),也实现了可滚动的选项卡(View宽度不固定同时可以横向滚动)。如果你使用ViewPager在 tab之间横向切换,你可以直接从PagerAdapter的getPageTitle() 中创建选项卡,然后使用setupWithViewPager()将两者联系在一起。它可以使tab的选中事件能更新ViewPager,同时 ViewPager 
的页面改变能更新tab的选中状态。

注意项:

如果你使用ViewPager在tab之间横向切换,切记可以直接从PagerAdapter的getPageTitle() 中创建选项卡,然后使用setupWithViewPager()将两者联系在一起。

2-6 NavigationView控件

在md风格的app中,例如如下风格的侧滑菜单非常常见:

22101117_rAoN.jpg

在之前的设计中,你可能需要考虑如何去布局实现,例如使用ListView;再者还要去设计Item的选中状态之类~~

but,现在,google提供了NavigationView,你只需要写写布局文件,这样的效果就ok了,并且兼容到Android 2.1,非常值得去体验一下。接下来我们来介绍如何去使用这个NavigationView


2-7 CoordinatorLayout控件

曾在网上找了一些关于CoordinatorLayout的教程,大部分文章都是把CoordinatorLayoutAppbarLayoutCollapsingToolbarLayout 以及Toolbar等一起使用来介绍,这让我不知不觉在心中认为把这几个布局要一起使用,而且只是用于那种场景中。其实CoordinatorLayout的功能并不是局限于与AppBarLayout一起使用,它的功能强大着呢,本文主要对CoordinatorLayout的使用进行介绍,后面再写一篇文章将AppBarLayoutCollapsingToolBarLayout整合CoordinatorLayout一起。那么到底CoordinatorLayout有多好用,请往下感受吧~

CoordinatorLayout能做什么

在学习CoordinatorLayout之前,很有必要了解CoordinatorLayout能帮我们做什么,从名字上可以看出,就是帮我们协调子View的。怎么个协调法呢?就是它根据我们的定制,帮助我们协调各个子View的布局。我们先看一组动画图~

CoordinatorLayout演示

稍微解释一下这个动画,蓝色的矩形是我们一个普通View,黄色的Hello是一个Button。我们水平拖动蓝色矩形时,黄色Button查着与蓝色矩形相反方向移动;竖直移动蓝色矩形时,黄色也跟着竖直。简而言之:它们在竖直方向同步移动,在水平方向相反。

这个效果如果让你不用CoordinatorLayout去实现,应该没有任何问题,但是代码的耦合度应该非常大,你的代码必须要持有2个View的引用,然后在onTouchEvent里面做各种判断。如果我们想要实现的功能是,有更多的View要根据蓝色的View的移动相应作出响应,那么那就得在蓝色ViewonTounchEvent里面针对其他的View处理各种逻辑。这耦合度未免太伤感了~

CoordinatorLayout既然号称能帮我们协调子View的布局,我们接下来看看CoordinatorLayout如何实现~

CoordinatorLayout使用

CoordinatorLayout的使用核心是BehaviorBehavior就是执行你定制的动作。在讲Behavior之前必须先理解两个概念:ChildDependency,什么意思呢?Child当然是子View的意思了,是谁的子View呢,当然是CoordinatorLayout的子View;其实Child是指要执行动作的CoordinatorLayout的子View。而Dependency是指Child依赖的View。比如上面的gif图中,蓝色的View就是Dependency,黄色的View就是Child,因为黄色的View的动作是依赖于蓝色的View。简而言之,就是如过Dependency这个View发生了变化,那么Child这个View就要相应发生变化。发生变化是具体发生什么变化呢?这里就要引入BehaviorChild发生变化的具体执行的代码都是放在Behavior这个类里面。

怎么使用Behavior呢,首先,我们定义一个类,继承CoordinatorLayout.Behavior<T>,其中,泛型参数T是我们要执行动作的View类,也就是Child。然后就是去实现Behavior的两个方法:

/**
* 判断child的布局是否依赖dependency
*/
   @Override
 public boolean layoutDependsOn(CoordinatorLayout parent, T child, View dependency) {
    boolean rs;
    //根据逻辑判断rs的取值
    //返回false表示child不依赖dependency,ture表示依赖
    return rs;  
}

/**
* 当dependency发生改变时(位置、宽高等),执行这个函数
* 返回true表示child的位置或者是宽高要发生改变,否则就返回false
*/
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, T child, View dependency) {
     //child要执行的具体动作
        return true;
}

有了上面的概念后,我们看看具体怎么去实现吧~

为了响应跟随手指移动的操作,我们定义一个非常简单的View,这个View只响应跟随手指移动,将这个View作为Dependency。由于过于简单,这个View源码不粘贴,我们只需知道这个View的类名叫:TempView

我们看看Behavior的使用:

package com.hc.studyCoordinatorLayout;

import android.content.Context;
import android.support.design.widget.CoordinatorLayout;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;
import android.widget.Button;

/**
 * Package com.hc.studyCoordinatorLayout
 * Created by HuaChao on 2016/6/1.
 */
public class MyBehavior extends CoordinatorLayout.Behavior<Button> {
    private int width;

    public MyBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
        DisplayMetrics display = context.getResources().getDisplayMetrics();
        width = display.widthPixels;
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, Button child, View dependency) {
        //如果dependency是TempView的实例,说明它就是我们所需要的Dependency
        return dependency instanceof TempView;
    }

    //每次dependency位置发生变化,都会执行onDependentViewChanged方法
    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, Button btn, View dependency) {

        //根据dependency的位置,设置Button的位置

        int top = dependency.getTop();
        int left = dependency.getLeft();

        int x = width - left - btn.getWidth();
        int y = top;

        setPosition(btn, x, y);
        return true;
    }

    private void setPosition(View v, int x, int y) {
        CoordinatorLayout.MarginLayoutParams layoutParams = (CoordinatorLayout.MarginLayoutParams) v.getLayoutParams();
        layoutParams.leftMargin = x;
        layoutParams.topMargin = y;
        v.setLayoutParams(layoutParams);
    }


}

OK,现在我们为Button类指定了Dependency,并且定义好了跟随Dependency一直变化的动作(Behavior),接下来我们就要指定好为哪个具体的Button实例来绑定这些。方法很简单,直接在布局文件指定就好:

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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"
    tools:context="com.hc.studyCoordinatorLayout.MainActivity">

    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="300dp"
        android:layout_marginTop="300dp"
        android:background="#FFCC00"
        android:text="Hello"
        app:layout_behavior="com.hc.studyCoordinatorLayout.MyBehavior" />

    <com.hc.studyCoordinatorLayout.TempView
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:layout_marginLeft="300dp"
        android:layout_marginTop="300dp"
        android:background="#3366CC"  />
</android.support.design.widget.CoordinatorLayout>

是不是很简单呢?我们只需关注Behavior的编写就好了,把ChildDependency之间的关系完全解耦了~

 

2-8 AppBarLayout控件

AppBarLayout继承自LinearLayout,布局方向为垂直方向。所以你可以把它当成垂直布局的LinearLayout来使用。AppBarLayout是在LinearLayou上加了一些材料设计的概念,它可以让你定制当某个可滚动View的滚动手势发生变化时,其内部的子View实现何种动作。

请注意:上面提到的某个可滚动View,可以理解为某个ScrollView。怎么理解上面的话呢?就是说,当某个ScrollView发生滚动时,你可以定制你的“顶部栏”应该执行哪些动作(如跟着一起滚动、保持不动等等)。那某个可移动的View到底是哪个可移动的View呢?这是由你自己指定的!如何指定,我们后面说。

2-8-1AppBarLayout子View的动作

内部的子View通过在布局中加app:layout_scrollFlags设置执行的动作,那么app:layout_scrollFlags可以设置哪些动作呢?分别如下:

(1) scroll:值设为scroll的View会跟随滚动事件一起发生移动。

什么意思呢?简单的说,就是当指定的ScrollView发生滚动时,该View也跟随一起滚动,就好像这个View也是属于这个ScrollView一样。

一张gif足以说明:

22101830_Amfc.jpg

scroll

对应的布局文件

<android.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="?android:attr/actionBarSize"
            android:background="?attr/colorPrimary"
            app:layout_scrollFlags="scroll" />
</android.support.design.widget.AppBarLayout>

(2) enterAlways:值设为enterAlways的View,当ScrollView往下滚动时,该View会直接往下滚动。而不用考虑ScrollView是否在滚动。

看个动画片(Y(^o^)Y)(ToolBar高度设为:?android:attr/actionBarSize,app:layout_scrollFlags="scroll|enterAlways"):

22101830_P0Ss.jpg

scroll|enterAlways

(3) exitUntilCollapsed:值设为exitUntilCollapsed的View,当这个View要往上逐渐“消逝”时,会一直往上滑动,直到剩下的的高度达到它的最小高度后,再响应ScrollView的内部滑动事件。

怎么理解呢?简单解释:在ScrollView往上滑动时,首先是View把滑动事件“夺走”,由View去执行滑动,直到滑动最小高度后,把这个滑动事件“还”回去,让ScrollView内部去上滑。看个gif感受一下(图中将高度设的比较大:200dp,并将最小高度设置为?android:attr/actionBarSize,app:layout_scrollFlags="scroll|exitUntilCollapsed"):

22101830_SBJk.jpg

scroll|exitUntilCollapsed

(4) enterAlwaysCollapsed:是enterAlways的附加选项,一般跟enterAlways一起使用,它是指,View在往下“出现”的时候,首先是enterAlways效果,当View的高度达到最小高度时,View就暂时不去往下滚动,直到ScrollView滑动到顶部不再滑动时,View再继续往下滑动,直到滑到View的顶部结束。

来个gif感受一下(图中将高度设的比较大:200dp,并将最小高度设置为?android:attr/actionBarSize,app:layout_scrollFlags="scroll|enerAlways|enterAlwaysCollapsed"):

22101830_SF6B.jpg

scroll|enerAlways|enterAlwaysCollapsed

2-8-2 将AppBarLayout与ScrollView关联起来

前面说了一直反复说“当ScrollView发生滚动时”,那么怎么将AppBarLayout与ScrollView关联起来呢?我们注意到,AppBarLayout与ScrollView之间动作“相互依赖”,这不就是我们上一篇《CoordinateLayout的使用如此简单 》所学的内容吗?把ScrollView和AppBarLayout作为CoordinateLayout的子View,然后编写一个Behavior,在这个Behavior里面判断当前的操作是应该让ScrollView时刻保持在AppBarLayout之下(即只要改变AppBarLayout的位置就可以一起滑动),还是应该让ScrollView内部滚动而不让AppBarLayout位置发生变化等等这些需求,都是可以在Behavior里面处理的。你可以去针对你的ScrollView编写Behavior。然而,我们看到我们的AppBarLayout事先的功能比较复杂,如果我们自己去定义这样的效果,代码非常复杂,还要考虑很多方面,好在Android帮我们写好啦,我们直接用就是了,这个ScrollView就是NestedScrollView,请注意,它并没有继承ScrollView,它继承的是FrameLayout,但是它实现的效果把它可以看成是ScrollView。

把NestedScrollView放入到我们的layout文件里面就可以啦~~~,很方便~

 <android.support.v4.widget.NestedScrollView

        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

       <!--将你的内容放在这里-->

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

有没有注意到有个属性:app:layout_behavior="@string/appbar_scrolling_view_behavior",它就是指定Behavior的,appbar_scrolling_view_behavior对应的类的名称是:android.support.design.widget.AppBarLayout$ScrollingViewBehavior感兴趣的可以去分析源码。

好了,我们现在会用AppBarLayout啦~是不是发现用起来so easy!接下来我们把剩下CollapsingToolbarLayout的给"消化"掉!

2-8-3 CollapsingToolbarLayout

CollapsingToolbarLayout是用来对Toolbar进行再次包装的ViewGroup,主要是用于实现折叠(其实就是看起来像伸缩~)的App Bar效果。它需要放在AppBarLayout布局里面,并且作为AppBarLayout的直接子ViewCollapsingToolbarLayout主要包括几个功能(参照了官方网站上内容,略加自己的理解进行解释):

(1) 折叠Title(Collapsing title):当布局内容全部显示出来时,title是最大的,但是随着View逐步移出屏幕顶部,title变得越来越小。你可以通过调用setTitle函数来设置title。

(2)内容纱布(Content scrim):根据滚动的位置是否到达一个阀值,来决定是否对View“盖上纱布”。可以通过setContentScrim(Drawable)来设置纱布的图片.

(3)状态栏纱布(Status bar scrim):根据滚动位置是否到达一个阀值决定是否对状态栏“盖上纱布”,你可以通过setStatusBarScrim(Drawable)来设置纱布图片,但是只能在LOLLIPOP设备上面有作用。

(4)视差滚动子View(Parallax scrolling children):子View可以选择在当前的布局当时是否以“视差”的方式来跟随滚动。(PS:其实就是让这个View的滚动的速度比其他正常滚动的View速度稍微慢一点)。将布局参数app:layout_collapseMode设为parallax

(5)将子View位置固定(Pinned position children):子View可以选择是否在全局空间上固定位置,这对于Toolbar来说非常有用,因为当布局在移动时,可以将Toolbar固定位置而不受移动的影响。 将app:layout_collapseMode设为pin

了解这些概念后,我们来看看布局吧~

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout 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.support.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            app:expandedTitleMarginEnd="64dp"
            app:expandedTitleMarginStart="48dp"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <ImageView
                android:id="@+id/main.backdrop"
                android:layout_width="wrap_content"
                android:layout_height="300dp"
                android:scaleType="centerCrop"
                android:src="@drawable/material_img"
                app:layout_collapseMode="parallax" />

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="?android:attr/actionBarSize"
                app:layout_collapseMode="pin"  />

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView

        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingTop="50dp"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/my_txt"
            android:textSize="20sp" />

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

</android.support.design.widget.CoordinatorLayout>

上面的都看得懂吧,每个陌生的属性都是讲过的哦,忘记了的话回头看,稍微解释一下,图片被设置为有视差的滑动,Toolbar设置为固定不动,另外,CollapsingToolbarLayout会对title进行放大和缩小,我们看看效果吧~

22101830_mmcZ.jpg

CollapsingToolbarLayout效果

如果你希望拖动过程中状态栏是透明的,可以在CollapsingToolbarLayout中加 app:statusBarScrim="@android:color/transparent",并且在onCreate中调用getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS)将状态栏设置为透明就好啦~

2-9 CollapsingToolbarLayout控件

我们来看一下CollapsingToolbarLayout的使用场景。

 

CollapsingToolbarLayout


可以看到,Toolbar的标题放大并在下方显示,当我们向上滑动列表时,顶部Header部分的图片向上折叠隐藏,标题向上移动并缩小,同时以渐显式的方式显示蓝色主题,直至高度缩为Toolbar的高度并成为Toolbar的背景色;向下滑动列表时,Header部分逐渐显示。这个效果就是利用了CollapsingToolbarLayout控件,在讲解案例代码前,先来介绍一下CollapsingToolbarLayout。

 

CollapsingToolbarLayout在 CollapsingToolbarLayout 的 Children 布局上,可以按照 FrameLayout 的属性来拍版,因为它本身继承于 FrameLayout :CollapsingToolbarLayout is a wrapper for Toolbar which implements a collapsing app bar. It is designed to be used as a direct child of a AppBarLayout.从官方对CollapsingToolbarLayout的介绍上可以看出,CollapsingToolbarLayout 是对 Toolbar 的一个包装,以达到折叠 AppBar 的交互视觉效果。所以,CollapsingToolbarLayout 的使用一定离不开 AppBarLayout 和 Toolbar,并且作为 AppBarLayout 的直接子视图使用。关于CollapsingToolbarLayout的属性在官网上可以查到,这里我只介绍案例中我们常用的几个属性:title标题,布局展开时放大显示在图片底部,布局折叠时缩小显示在Toolbar左侧。注意,没有设置这个属性时,默认使用Toolbar的标题;statusBarScrim顶部视图折叠状态下,状态栏的遮罩色。通常这样设置:app:statusBarScrim="?attr/colorPrimaryDark",即style样式中定义的沉浸式状态栏颜色。这个属性要和getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);(支持API19及以上版本,位于setContentView语句前面)一起使用,使顶部视图展开时图片能够延伸到状态栏位置显示,如效果图中所示;contentScrim内容遮罩,上下滚动时图片上面显示和隐藏的遮罩色,Toolbar位置的的背景色;通常这样设置:app:contentScrim="?attr/colorPrimary",即显示为Toolbar颜色,应用的主题色;layout_collapseMode折叠模式,设置其他控件滚动时自身的交互行为,有两种取值:parallax,折叠视差效果,比如上述效果图中的图片;pin,固定别针效果,比如上图中的Toolbar;layout_collapseParallaxMultiplier不折叠视差系数,配合parallax模式使用,取值有点类似alpha(不透明度),在0.0 ~ 1.0之间,默认值为0.5。当设置为1.0,滚动列表时图片不会折叠移动;

代码实现:

 


关于CoordinatorLayout作为根布局容器如何协调子控件之间的交互行为,可以参考上一篇文章,这里我介绍一下本例中几个新的注意点。作为AppBarLayout的直接子控件,CollapsingToolbarLayout包裹Header部分的ImageView和Toolbar,并分别设置二者的折叠模式。这个例子,我们给CollapsingToolbarLayout的layout_scrollFlags属性值设为:scroll|exitUntilCollapsed,其中exitUntilCollapsed表示控件向上折叠退出并以最小高度停留在顶部;前面介绍CollapsingToolbarLayout属性时介绍到了statusBarScrim的使用,其实也可以通过android:fitsSystemWindows和values-v21中style样式的statusBarColor和windowDrawsSystemBarBackgrounds属性来完成状态栏的背景色变化,详情参考源码即可;通过layout_anchor和layout_anchorGravity可以控制FloatingActionButton的behavior和位置,如上图所示,当滚动列表是,FAB按钮会随着AppBarLayout而显示和隐藏,并自带缩放动画。

示例源码我在GitHub上建立了一个Repository,用来存放整个Android Material Design系列控件的学习案例,会伴随着文章逐渐更新完善,欢迎大家补充交流,

2-10 新加了一个Bottom Sheets控件

如果使用上遇到坑,点击链接加入群【GitHub小伙伴交流群'''】:http://jq.qq.com/?_wv=1027&k=27lxYHB''' ,群号:477826523 帮你搞定一切bug...

Android Support Library 23.2里的 Design Support Library新加了一个Bottom Sheets控件,一个底部表,就是我们经常在分享或者地图、音乐等app看到的效果

22100157_mDb5.jpg

22100158_IlDx.jpg

昨天晚上Support Library 23.2包还没能更新,官方视频就已经透露出了,视频地址,从视频看出Support Library 23.2包新增了:

    1. Support Vector Drawables and Animated Vector Drawables
    1. AppCompat DayNight theme
    1. Design Support Library: Bottom Sheets
    1. Support v4: MediaBrowserServiceCompat
    1. RecyclerView
    1. Custom Tabs
    1. Leanback for Android TV

具体可以上官网博客看看。

这篇文章我给大家说说BottomSheetBehavior的使用及注意的地方

##Usage ###(1)在布局文件xml中

<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cl"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:fitsSystemWindows="true"
    >

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/bottom_sheet"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:behavior_hideable="true"
        app:behavior_peekHeight="50dp"
        app:layout_behavior="@string/bottom_sheet_behavior"
        >
          <!-- NestedScrollView里设置你的底部表长什么样的-->
    </android.support.v4.widget.NestedScrollView>
</android.support.design.widget.CoordinatorLayout>

###(2)在java代码中

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ns);

        // The View with the BottomSheetBehavior
        CoordinatorLayout coordinatorLayout = (CoordinatorLayout) findViewById(R.id.cl);
        View bottomSheet = coordinatorLayout.findViewById(R.id.bottom_sheet);
        final BottomSheetBehavior behavior = BottomSheetBehavior.from(bottomSheet);
        behavior.setBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
            @Override
            public void onStateChanged(@NonNull View bottomSheet, int newState) {
                //这里是bottomSheet 状态的改变回调
            }

            @Override
            public void onSlide(@NonNull View bottomSheet, float slideOffset) {
                //这里是拖拽中的回调,根据slideOffset可以做一些动画
            }
        });
    }

其实也挺简单的,我来解释一下。通过附加一个BottomSheetBehavior 给CoordinatorLayout的子视图,上文xml中的是NestedScrollView(adding app:layout_behavior = " android.support.design.widget.BottomSheetBehavior”),当然,RecyclerView也是可以的。如果需要BottomSheet View可以保持滚动,需要支持 nested scrolling (例如: NestedScrollView, RecyclerView, or ListView/ScrollView on API 21+).

app:behavior_hideable="true"
     app:behavior_peekHeight="50dp"

这两个属性我说说,peekHeight是当Bottom Sheets关闭的时候,底部下表我们能看到的高度,hideable 是当我们拖拽下拉的时候,bottom sheet是否能全部隐藏。 如果你需要监听Bottom Sheets回调的状态,可以通过setBottomSheetCallback来实现,onSlide方法是拖拽中的回调,根据slideOffset可以做一些动画 onStateChanged方法可以监听到状态的改变,总共有5种

  • STATE_COLLAPSED: 关闭Bottom Sheets,显示peekHeight的高度,默认是0
  • STATE_DRAGGING: 用户拖拽Bottom Sheets时的状态
  • STATE_SETTLING: 当Bottom Sheets view摆放时的状态。
  • STATE_EXPANDED: 当Bottom Sheets 展开的状态
  • STATE_HIDDEN: 当Bottom Sheets 隐藏的状态

我也简单的写了BottomSheetBehavior和BottomSheetDialog的demo,你可以看我源码是怎么用的 22100205_QkmB.gif 22100209_k3Eo.gif 22100212_SlZm.gif

使用就这些了,接下来我们来讲讲该注意的地方,应该说怎样更好的使用它。

###(1)关闭Bottom Sheets的行为 可以通过下图的形式,拖拽、点击bottom sheet之外的地方和通过‘x’按钮

22100221_ssZS.jpg

22100221_1GJP.jpg

22100221_tu6v.jpg

###(2)合适的视图设计

22100222_ILnz.jpg

22100222_uj3J.jpg

上图你可明显的看到第二幅这种设计是不合适的,空白太多,不美观,对吧!

22100222_r6KV.jpg

22100222_5uBm.jpg

如果Bottom Sheets 展开或者上拉覆盖了ActionBar or ToolBar 这种方式也是不合适的.

###(3)尺寸的设计 为了符合Material Design 设计,我们对尺寸有严格的要求,当然,你想随意我也阻止不了

22100222_lDJX.jpg

22100222_r5qq.jpg

22100222_THGH.jpg

我想说的就这些了,如果还有补充,欢迎PR!

3 总结

到此2015 Google IO的新suppory包控件完全介绍完毕。详细细节可以科学上网阅读AD的developer->tools->support library。至此只能期待Android M尽快发布呀。

PS:已经用上了Android Studio 1.3预览版,只是M得编译会出错,有BUG,别的暂时没发现啥区别,还有一点,比1.2貌似快了一点,哈哈,是我心里作用么?

下载Demo请点击:Design Support Library Demo

【工匠若水 http://blog.csdn.net/yanbober 转载烦请注明出处,尊重分享成果】

转载于:https://my.oschina.net/u/1756702/blog/864384

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值