AppBarLayout 简单使用

导读

本篇文章将介绍Materia_Design控件,design包中的AppBarLayout的简单使用说明

控件简介

  • AppbarLayout继承于LinearLayout,是一个垂直的LinearLayout,它实现了Material Design的许多功能和特性,即滚动手势(Scrolling Gestures)

  • 我们可以定义行为Behavior,当某个可滑动View(如ListView)滑动手势发生改变时,AppbarLayout 内部的子View该做什么动作

  • AppBarLayout需要使用AppBarLayout.ScrollingViewBehavior behavior 行为类绑定一个滚动的View,以便知道何时结束滚动 app:layout_behavior=”@string/appbar_scrolling_view_behavior”

  • AppbarLayout严重依赖于CoordinatorLayout,必须作为CoordinatorLayout的子View来使用.如果在不同的ViewGroup中使用AppbarLayout,那么会有大部分的功能无效.

  • AppBarLayout 依赖于CoordinatorLayout,一般结合ToolBar和TabLayout,以及滚动View(ScrollView/NestedScrollView)使用


属性说明

属性说明
app:elevation设置阴影 (已废弃)
android:stateListAnimator用于解决设置阴影方案 Api>=21
app:expanded设置AppBarLayout默认的状态(ture为展开,false为折叠) 要同时设置 app:layout_scrollFlags 才有效果
app:layout_scrollFlags5种状态 scroll,enterAlways,enterAlwaysCollapsed,exitUntilCollapsed,snap

几个常用的API (代码中使用)

属性说明
addOnOffsetChangedListener当AppbarLayout 的竖直方向偏移量发生改变的时候回调
removeOnOffsetChangedListener移除offsetChanged监听器
setExpanded (boolean expanded)设置AppbarLayout 是展开状态还是折叠状态,默认有动画
setExpanded (boolean expanded, boolean animate)设置AppbarLayout 是展开状态还是折叠状态,animate 参数控制切换到新的状态时是否需要动画
setOrientation设置AppbarLayout里的子View排列方向
getTotalScrollRange返回AppbarLayout 里的所有子View的滑动范围

五种状态效果说明

Scroll

AppBarLayoutd的子View设置了该属性时,这个View将跟随滚动View滚动(效果类似滚动view设置了headview)

换句话说->默认显示Toolbar的layout_height内容,跟随ScrollView滚动

image

enterAlways

其实就是向下滚动时ScrollView和Child View之间的滚动优先级问题.对比scroll和scroll | enterAlways设置,当向下滑动时,前者优先滚动ScrollView,后者优先滚动Child View,当优先滚动的一方已经全部滚进屏幕之后,另一方才开始滚动.

换句话说->默认显示Toolbar的layout_height,上滑时Toolbar跟随ScrollView,下滑时不用滑动到底部就显示完上滑时Toolbar跟随ScrollView的layout_height的内容

注意需要 scroll | enterAlways 搭配使用,否则滑动没响应

这里写图片描述

enterAlwaysCollapsed

AppBarLayoutd的子View设置了该属性时,当滚动View向下滑到最低时,子View会继续滑动一部分距离,这部分距离通过子View设置的android:minHeight决定

换句话说->默认显示Toolbar的部分layout_height内容,上滑跟随ScrollView滚动,下滑先显示Toolbar设置的minHeight部分内容,下滑到底部再显示Toolbar完整的layout_height

需要scroll | enterAlways | enterAlwaysCollapsed 搭配使用

这里写图片描述

exitUntilCollapsed

AppBarLayoutd的子View设置了该属性时,当滚动View向下滑到最低时,子View会继续滑动一部分距离,这部分距离通过子View设置的android:minHeight 决定,但滚动view向上滑动一直到底前,子view设置的minHeight高度保持固定

换句话说->默认显示Toolbar的layout_height内容,上滑显示Toolbar设置的minHeight内容,下滑到底部前先显示Toolbar设置的minHeight内容,下滑到底部后继续下滑显示Toolbar的layout_height内容

需要scroll | exitUntilCollapsed 搭配使用

这里写图片描述

snap

AppBarLayoutd的子View设置了该属性时,当滚动View向下滑动超出其25%,被拉伸的子View会将滚动View回滑到子View固定高度android:minHeight,滚动View向上滑动时同理

换句话说->默认显示Toolbar的layout_height内容.上滑时,当layout_height显示少于一半松手,layout_height内容自动滚出屏幕理,下滑时,当layout_height显示多余一半松手,layout_height的内容全部滚进屏幕

需要scroll | snap 搭配使用

这里写图片描述


控件使用说明

准备工作


    compile 'com.android.support:appcompat-v7:26.0.0-alpha1'
    compile 'com.android.support:design:26.0.0-alpha1'
  • 1
  • 2
  • 3
  • 4

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:layout_width="match_parent"
    android:layout_height="match_parent">


    <android.support.v4.widget.NestedScrollView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

            <!--测试文本,随便自定义就好-->
            <TextView
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:text="@string/AppbarLayout_content_tv"/>

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

    <!--app:elevation   设置阴影(已废弃)-->
    <!--android:stateListAnimator="@animator/appbar_elevation" 解决设置阴影的方案,Api>21 可用-->
    <!--app:expanded  设置AppBarLayout默认的状态(ture为展开,false为折叠)-->
    <android.support.design.widget.AppBarLayout
        android:id="@+id/appbarLayout"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:stateListAnimator="@animator/appbar_elevation"
        android:background="@color/colorGrey">

        <!--app:layout_scrollFlags 有五种状态-->
        <!--scroll-->
        <!--scroll|enterAlways-->
        <!--scroll|enterAlways|enterAlwaysCollapsed-->
        <!--scroll|exitUntilCollapsed-->
        <!--scroll|snap-->
        <android.support.v7.widget.Toolbar
            android:id="@+id/toolbar"
            android:layout_width="match_parent"
            android:layout_height="200dp"
            android:layout_margin="10dp"
            android:gravity="bottom"
            android:minHeight="56dp"
            app:title="AppBar Layout"
            app:titleTextColor="@color/colorWhite"/>

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

</android.support.design.widget.CoordinatorLayout>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52

代码动态使用

  1. 设置app:expanded属性

在Activity类,findViewById 找到AppBarLayout控件,然后设置相应的属性

AppBarLayout.setExpanded(true);
  • 1
  • 2
  • 3
  • 4
  • 5
  1. 设置app:layout_scrolllFlags 五种状态

在Activity类,findViewById 找到AppBarLayout的子控件(如Toolbar),然后通过AppBarLayout.LayoutParams给子控件设置ScrollFlags

1. scroll

      AppBarLayout.LayoutParams mLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
             mLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL);

---

2. scroll | enterAlways

      AppBarLayout.LayoutParams mLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
             mLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
                        | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS);

---

3. scroll|enterAlways|enterAlwaysCollapsed

      AppBarLayout.LayoutParams mLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
             mLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
                        | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS
                        | AppBarLayout.LayoutParams.SCROLL_FLAG_ENTER_ALWAYS_COLLAPSED);

---

4. scroll|exitUntilCollapsed

      AppBarLayout.LayoutParams mLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
             mLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
                        | AppBarLayout.LayoutParams.SCROLL_FLAG_EXIT_UNTIL_COLLAPSED);

---

5. scroll|snap

      AppBarLayout.LayoutParams mLayoutParams = (AppBarLayout.LayoutParams) mToolbar.getLayoutParams();
             mLayoutParams.setScrollFlags(AppBarLayout.LayoutParams.SCROLL_FLAG_SCROLL
                        | AppBarLayout.LayoutParams.SCROLL_FLAG_SNAP);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  1. 取代app:elevation的设置阴影方法

res/animator/目录下新建appbar_elevation.xml文件

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <objectAnimator
            android:duration="1"
            android:propertyName="elevation"
            android:valueTo="2dp"
            android:valueType="floatType"/>
    </item>
</selector>

---

在Activity类,findViewById 找到AppBarLayout控件,然后设置相应的属性

AppBarLayout.setStateListAnimator(AnimatorInflater.loadStateListAnimator(getContext(), R.animator.appbar_elevation));
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

注意事项/爬坑(bug处理)

  1. 对应的Flag要结合起来一起用
  2. app:elevation属性被废弃了,使用StateListAnimator()方式实现阴影效果

扩展

这里说下阴影这样设置的原因(查看设置阴影的API setTargetElevation()源码)


/**
     * @deprecated target elevation is now deprecated. AppBarLayout's elevation is now
     * controlled via a {@link android.animation.StateListAnimator}. If a target
     * elevation is set, either by this method or the {@code app:elevation} attribute,
     * a new state list animator is created which uses the given {@code elevation} value.
     *
     * @attr ref android.support.design.R.styleable#AppBarLayout_elevation
     */
@Deprecated
public void setTargetElevation(float elevation) {    
    if (Build.VERSION.SDK_INT >= 21) {       
        ViewUtilsLollipop.setDefaultAppBarLayoutStateListAnimator(this, elevation);
    }
}

---

/**
     * @deprecated target elevation is now deprecated. AppBarLayout's elevation is now
     * controlled via a {@link android.animation.StateListAnimator}. This method now
     * always returns 0.
     */
@Deprecated
public float getTargetElevation() {return 0;}

通过查看注释可知google提供了我们解决方案:StateListAnimator
(不过要注意Api>=21才能使用)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

总结

官方控件虽好,但如果不能满足开发需求,建议自定义控件实现自己的效果

本篇文章到此结束,欢迎关注,后续补充behavior用法,有问题也欢迎评论,共同成长

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值