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_scrollFlags 5种状态 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
换句话说->默认显示Toolbar的layout_height内容,跟随ScrollView滚动
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>
代码动态使用
设置app:expanded属性
在Activity类,findViewById 找到AppBarLayout控件,然后设置相应的属性
AppBarLayout.setExpanded(true);
12345
设置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);
取代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处理)
对应的Flag要结合起来一起用
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才能使用)