导读
本篇文章将介绍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
AppBarLayoutd的子View设置了该属性时,这个View将跟随滚动View滚动(效果类似滚动view设置了headview)
换句话说->默认显示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'
- 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
代码动态使用
- 设置app:expanded属性
在Activity类,findViewById 找到AppBarLayout控件,然后设置相应的属性
AppBarLayout.setExpanded(true);
- 1
- 2
- 3
- 4
- 5
- 设置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
- 取代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处理)
- 对应的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才能使用)
- 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用法,有问题也欢迎评论,共同成长