随笔博文

AppBarLayout 简单使用

2022-12-02 10:58:17 michael007js 414

导读

本篇文章将介绍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'

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. 设置app:expanded属性

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

AppBarLayout.setExpanded(true);
12345
  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. 取代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));

注意事项/爬坑(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才能使用)


首页
关于博主
我的博客
搜索