介紹
CoordinatorLayout是用來協(xié)調(diào)其子view們之間動作的一個父view,而Behavior就是用來給CoordinatorLayout的子view們實現(xiàn)交互的赃额。
SUM
1. CollapsingToolbarLayout_伸縮折疊工具
參考:看熄守,這個工具欄能伸縮折疊——Android CollapsingToolbarLayout使用介紹
a. CollapsingToolbarLayout折疊或展開時励幼,F(xiàn)loatingActionButton跟隨運動并且大小相應變化.CollapsingToolbarLayout是專門用來實現(xiàn)子布局內(nèi)不同元素響應滾動細節(jié)的布局。
b. AppBarLayout是一種支持響應滾動手勢的app bar布局(比如工具欄滾出或滾入屏幕)雕什;與AppBarLayout組合的滾動布局(Recyclerview缠俺、NestedScrollView等)需要設置app:layout_behavior="@string/appbar_scrolling_view_behavior"(上面代碼中NestedScrollView控件所設置的)。沒有設置的話贷岸,AppBarLayout將不會響應滾動布局的滾動事件壹士。。
c. CollapsingToolbarLayout和ScrollView一起使用會有滑動bug偿警,注意要使用NestedScrollView來替代ScrollView躏救。
Android studio中有一個Activity模板叫ScrollingActivity,它實現(xiàn)的就是簡單的可折疊工具欄螟蒸。
ScrollingActivity的布局代碼如下:
<?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"
android:fitsSystemWindows="true"
tools:context="com.jack.jack_junit_demo.ScrollingActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:fitsSystemWindows="true"
android:layout_height="180dp"
android:layout_width="match_parent"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:contentScrim="?attr/colorPrimary">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_height="?attr/actionBarSize"
android:layout_width="match_parent"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<!--可以include 抽取出來-->
<android.support.v4.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/text_margin"
android:text="@string/large_text" />
</android.support.v4.widget.NestedScrollView>
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/fab_margin"
app:layout_anchor="@id/app_bar"
app:layout_anchorGravity="bottom|end"
android:src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
2.AppBarLayout的子布局有5種滾動標識
就是上面代碼CollapsingToolbarLayout中配置的app:layout_scrollFlags屬性:
- scroll:將此布局和滾動時間關聯(lián)盒使。這個標識要設置在其他標識之前,沒有這個標識則布局不會滾動且其他標識設置無效七嫌。
- enterAlways:任何向下滾動操作都會使此布局可見少办。這個標識通常被稱為“快速返回”模式。
- enterAlwaysCollapsed:假設你定義了一個最小高度(minHeight)同時enterAlways也定義了诵原,那么view將在到達這個最小高度的時候開始顯示英妓,并且從這個時候開始慢慢展開挽放,當滾動到頂部的時候展開完。
- exitUntilCollapsed:當你定義了一個minHeight蔓纠,此布局將在滾動到達這個最小高度的時候折疊骂维。
- snap:當一個滾動事件結束,如果視圖是部分可見的贺纲,那么它將被滾動到收縮或展開航闺。例如,如果視圖只有底部25%顯示猴誊,它將折疊潦刃。相反,如果它的底部75%可見懈叹,那么它將完全展開乖杠。
3.CollapsingToolbarLayout的contentScrim、statusBarScrim 屬性澄成。
- app:contentScrim設置折疊時工具欄布局的顏色
- app:statusBarScrim設置折疊時狀態(tài)欄的顏色胧洒。
默認contentScrim是colorPrimary的色值,statusBarScrim是colorPrimaryDark的色值墨状。這個后面會用到卫漫。
4.CollapsingToolbarLayout子布局設置折疊模式,app:layout_collapseMode**
- off:這個是默認屬性肾砂,布局將正常顯示列赎,沒有折疊的行為。
- pin:CollapsingToolbarLayout折疊后镐确,此布局將固定在頂部包吝。
- parallax:CollapsingToolbarLayout折疊時,此布局也會有視差折疊效果
當CollapsingToolbarLayout的子布局設置了parallax模式時源葫,我們還可以通過
app:layout_collapseParallaxMultiplier
設置視差滾動因子诗越,值為:0~1。
5.FloatingActionButton
FloatingActionButton這個控件通過app:layout_anchor這個設置錨定在了AppBarLayout下方息堂。FloatingActionButton源碼中有一個Behavior方法嚷狞,當AppBarLayout收縮時,F(xiàn)loatingActionButton就會跟著做出相應變化储矩。關于CoordinatorLayout和Behavior感耙,我下一篇文章會和大家一起學習。
B站很早就開源了一個彈幕引擎持隧,還起了個狂拽酷炫吊炸天的名字叫“烈焰彈幕使 ”(一看就是二次元程序猿們的作品→_→)即硼,源碼在github上,項目名叫DanmakuFlameMaster屡拨。
2. 自定義CoordinatorLayout的Behavior
自定義Behavior模仿知乎
參考:http://www.reibang.com/p/488283f74e69
1.先看下布局
<?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/behavior_demo_coordinatorLayout"
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/AppTheme.AppBarOverlay">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways|snap"
android:background="?attr/colorPrimary" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.widget.SwipeRefreshLayout
android:id="@+id/behavior_demo_swipe_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<android.support.v7.widget.RecyclerView
android:id="@+id/behavior_demo_recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</android.support.v4.widget.SwipeRefreshLayout>
<!--行為只酥,依賴于自定義Beavior-->
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="16dp"
android:layout_marginBottom="72dp"
android:src="@android:drawable/ic_dialog_email"
app:layout_behavior="com.example.zcp.coordinatorlayoutdemo.behavior.MyFabBehavior"
android:layout_gravity="bottom|right" />
<!--行為褥实,依賴于自定義Beavior-->
<LinearLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_gravity="bottom"
android:background="@color/colorPrimary"
android:gravity="center"
app:layout_behavior="com.example.zcp.coordinatorlayoutdemo.behavior.MyBottomBarBehavior">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:textColor="#ffffff"
android:text="這是一個底欄"/>
</LinearLayout>
</android.support.design.widget.CoordinatorLayout>
SwipeRefreshLayout、FloatingActionButton和當做底欄的LinearLayout上有一個app:layout_behavior配置裂允。
SwipeRefreshLayout配置的"@string/appbar_scrolling_view_behavior"是系統(tǒng)提供的损离,用來使滑動控件與AppBarLayout互動。
FloatingActionButton和底欄上配置的是我們接下來要自定義的Behavior绝编。
先看FloatingActionButton的Behavior僻澎。
public class MyFabBehavior extends CoordinatorLayout.Behavior<View> {
private static final Interpolator INTERPOLATOR = new FastOutSlowInInterpolator();
private float viewY;//控件距離coordinatorLayout底部距離
private boolean isAnimate;//動畫是否在進行
public MyFabBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onStartNestedScroll(CoordinatorLayout coordinatorLayout, View child, View directTargetChild, View target, int nestedScrollAxes) {
if (child.getVisibility() == View.VISIBLE && viewY == 0) {
//獲取控件距離父布局(coordinatorLayout)底部距離
viewY = coordinatorLayout.getHeight() - child.getY();
}
return (nestedScrollAxes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;//判斷是否豎直滾動
}
@Override
public void onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) {
//大于0是向上滾動 小于0是向下滾動
if (dy >= 0 && !isAnimate && child.getVisibility() == View.VISIBLE) {
hide(child);
} else if (dy < 0 && !isAnimate && child.getVisibility() == View.GONE) {
show(child);
}
}
//隱藏時的動畫
private void hide(final View view) {
ViewPropertyAnimator animator = view.animate().translationY(viewY).setInterpolator(INTERPOLATOR).setDuration(200);
animator.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
isAnimate = true;
}
@Override
public void onAnimationEnd(Animator animator) {
view.setVisibility(View.GONE);
isAnimate = false;
}
@Override
public void onAnimationCancel(Animator animator) {
show(view);
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
animator.start();
}
//顯示時的動畫
private void show(final View view) {
ViewPropertyAnimator animator = view.animate().translationY(0).setInterpolator(INTERPOLATOR).setDuration(200);
animator.setListener(new Animator.AnimatorListener() {
@Override
public void onAnimationStart(Animator animator) {
view.setVisibility(View.VISIBLE);
isAnimate = true;
}
@Override
public void onAnimationEnd(Animator animator) {
isAnimate = false;
}
@Override
public void onAnimationCancel(Animator animator) {
hide(view);
}
@Override
public void onAnimationRepeat(Animator animator) {
}
});
animator.start();
}
}
邏輯并不復雜,我們通過重寫B(tài)ehavior中關于嵌套滑動的兩個回調(diào)完成了FloatingActionButton的隱藏和顯示判斷及操作十饥。
單獨出場的底欄也可以利用上面一樣的方法來設置隱藏或顯示窟勃,我的底欄是和AppBarLayout一起出場,所以我就讓底欄從屬于AppBarLayout活動逗堵。代碼如下:
public class MyBottomBarBehavior extends CoordinatorLayout.Behavior<View> {
public MyBottomBarBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
//這個方法是說明這個子控件是依賴AppBarLayout的
return dependency instanceof AppBarLayout;
}
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
float translationY = Math.abs(dependency.getTop());//獲取更隨布局的頂部位置
child.setTranslationY(translationY);
return true;
}
}
代碼量比上個還少秉氧。我們還可以通過重寫onMeasureChild()來使控件響應從屬控件的大小變化。
Behavior提供的很多蜒秤,我這里用到的只是一部分汁咏,大家可以看看源碼,根據(jù)具體需求去使用作媚。
3 .CollapsingToolbarLayout與TabLayout結合
CollapsingToolbarLayout與TabLayout組合使用的效果也不錯攘滩。
<?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"
android:fitsSystemWindows="true">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="250dp"
android:fitsSystemWindows="true"
android:theme="@style/AppTheme.AppBarOverlay">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/toolbar_layout"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:titleEnabled="false"
android:fitsSystemWindows="true"
app:contentScrim="@color/colorPrimary"
app:statusBarScrim="@android:color/transparent"
app:layout_scrollFlags="scroll|exitUntilCollapsed|snap">
<ImageView
android:id="@+id/imageview"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.7"
android:fitsSystemWindows="true"
android:src="@drawable/girl2"/>
<View
android:layout_width="match_parent"
android:layout_height="40dp"
android:background="@drawable/gradient"
android:fitsSystemWindows="true" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="96dp"
android:minHeight="?attr/actionBarSize"
android:gravity="top"
app:layout_collapseMode="pin"
app:title="hello"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:titleMarginTop="15dp"
/>
<android.support.design.widget.TabLayout
android:id="@+id/tablayout"
android:layout_width="match_parent"
android:layout_height="45dp"
android:layout_gravity="bottom" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpage"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
</android.support.v4.view.ViewPager>
</android.support.design.widget.CoordinatorLayout>
2. AppBarLayout
- SwipeRefreshLayout配置的"@string/appbar_scrolling_view_behavior"是系統(tǒng)提供的,用來使滑動控件與AppBarLayout互動掂骏。