CoordinatorLayout有什么用
在 2015 年的 I/O 开发者大会上,Google 介绍了一个新的 Android Design Support Library,该库可以帮助开发者在应用上使用 Meterial Design。它包含了许多重要的 Meterial Design 的构建块,并且它支持 API 7及以上的版本。 在库中就包含一个CoordinatorLayout
,它是一个 FrameLayout
。该布局的强大在于,能够协调子元素之间的依赖关系。CoordinatorLayout
使用新的思路通过协调调度子布局的形式实现触摸影响布局的形式产生动画效果。CoordinatorLayout
通过设置子View
的Behaviors
来调度子View
。Library中提供了AppBarLayout.Behavior
, AppBarLayout.ScrollingViewBehavior
, FloatingActionButton.Behavior
, SwipeDismissBehavior<V extends View>
等。
CoordinatorLayout如何使用
使用CoordinatorLayout
需要在app目录中build.gradle
加入Support Design Library:
compile 'com.android.support:design:25.1.0'
接下来我们看看官方的效果,首先我们新建一个项目,然后在Add an Activity to Mobile
中选择Scrolling Activity
。
接下来我们看一看Android Studio自动帮我们生成的代码。
activity_scrolling.xml
<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="me.shihao.coordinatorlayoutusage.ScrollingActivity">
<android.support.design.widget.AppBarLayout
android:id="@+id/app_bar"
android:layout_width="match_parent"
android:layout_height="@dimen/app_bar_height"
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"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_collapseMode="pin"
app:popupTheme="@style/AppTheme.PopupOverlay"/>
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<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"
app:srcCompat="@android:drawable/ic_dialog_email"/>
<include layout="@layout/content_scrolling"/>
</android.support.design.widget.CoordinatorLayout>
<a name="1"></a>
content_scrolling.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.v4.widget.NestedScrollView
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"
app:layout_behavior="@string/appbar_scrolling_view_behavior"
tools:context="me.shihao.coordinatorlayoutusage.ScrollingActivity"
tools:showIn="@layout/activity_scrolling">
<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>
ScrollingActivity.java
public class ScrollingActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_scrolling);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.menu_scrolling, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
//noinspection SimplifiableIfStatement
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
运行效果
效果显示,视图滚动时Toolbar会折叠,这个效果是Android Support Library里面新增的CoordinatorLayout
, AppBarLayout
,CollapsingToolbarLayout
实现的。根据官方的文档,AppBarLayout
必须是CoordinatorLayout
的直接子View
。然后,我们需要定义AppBarLayout
与滚动视图之间的联系。在content_scrolling.xml中为可滚动视图NestedScrollView
的添加了app:layout_behavior
。support library包含了一个特殊的字符串资源@string/appbar_scrolling_view_behavior
,它和AppBarLayout.ScrollingViewBehavior
相匹配,用来通知AppBarLayout
这个特殊的view何时发生了滚动事件,这个behavior需要设置在触发事件(滚动)的view之上。当CoordinatorLayout
发现NestedScrollView
中定义了这个属性,它会搜索自己所包含的其他view
,看看是否有view
与这个behavior
相关联。AppBarLayout.ScrollingViewBehavior
描述了NestedScrollView
与AppBarLayout
之间的依赖关系。NestedScrollView
的任意滚动事件都将触发AppBarLayout
或者AppBarLayout
里面view
的改变。AppBarLayout
里面定义的view
只要设置了app:layout_scrollFlags
属性,就可以在NestedScrollView
滚动事件发生的时候被触发。
CollapsingToolbarLayout
CollapsingToolbarLayout
作用是提供了一个可以折叠的Toolbar
,它继承至FrameLayout
,给它设置layout_scrollFlags
,它可以控制包含在CollapsingToolbarLayout
中的控件(如:ImageView
、Toolbar
)在响应layout_behavior
事件时作出相应的scrollFlags
滚动事件(移除屏幕或固定在屏幕顶端)。CollapsingToolbarLayout
提供以下属性和方法使用:
- title:
ToolBar
的标题,当CollapsingToolbarLayout
全屏没有折叠时,title
显示的是大字体,在折叠的过程中,title
不断变小到一定大小的效果。你可以调用setTitle(CharSequence)
方法设置title
。 - contentScrim:
ToolBar
被折叠到顶部固定时候的背景,你可以调用setContentScrim(Drawable)
方法改变背景。 - statusBarScrim:状态栏的背景,调用方法
setStatusBarScrim(Drawable)
。 - layout_collapseParallaxMultiplier:
CollapsingToolbarLayout
滑动时,子视图的视觉差,值的范围[0.0,1.0],值越大视觉差越大。 - layout_collapseMode :子视图的折叠模式,在子视图设置,有两种
pin
:固定模式,在折叠的时候最后固定在顶端;parallax
:视差模式,在折叠的时候会有个视差折叠的效果。
app:layout_scrollFlags
在app:layout_scrollFlags
属性里面必须至少启用scroll
这个flag
,这样这个view才会滚动,否则它将一直固定在顶部。并且要把带有scroll flag
的view
放在前面,这样收回的view
才能让正常退出,而固定的view
继续留在顶部。可以使用的其他flag有:
- scroll::所有想滚动出屏幕的view都需要设置这个flag, 没有设置这个flag的view将被固定在屏幕顶部。
- enterAlways::一旦向下滚动这个view就可见。
- enterAlwaysCollapsed::顾名思义,这个flag定义的是何时进入(已经消失之后何时再次显示)。假设你定义了一个最小高度(minHeight)同时enterAlways也定义了,那么view将在到达这个最小高度的时候开始显示,并且从这个时候开始慢慢展开,当滚动到顶部的时候展开完。
- exitUntilCollapsed::滚动退出屏幕,最后折叠在顶端。
CoordinatorLayout
还提供了一个layout_anchor
的属性,连同 layout_anchorGravity
一起,可以用来放置与其他视图关联在一起的悬浮视图(如 FloatingActionButton
)。如本例中使用FloatingActionButton
。通过下面的参数设置了FloatingActionButton
的位置,两个属性共同作用使得浮动按钮也能折叠消失展现。
app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|right|end"
总结
实现折叠效果,需要注意下面几点:
- 顶层布局为
CoordinatorLayout
。 -
AppBarLayout
的高度固定。 -
CollapsingToolbarLayout
的子视图设置app:layout_scrollFlags
属性 - 关联滚动视图(如本例中的
NestedScrollView
)设置属性app:layout_behavior
。 - 关联悬浮视图(如本例中的
FloatingActionButton
)设置app:layout_anchor
,app:layout_anchorGravity
属性
当然CoordinatorLayout
功能还强大,而他的神奇之处在于Behavior
对象,CoordinatorLayout
自己并不控制View
,所有的控制权都在Behavior
。比如前面用到的FloatingActionButton.Behavior
,AppBarLayout.Behavior
, AppBarLayout.ScrollingViewBehavior
。当然我们可以通过自定义的方式来实现自己的Behavior
,来实现更多样的功能。自定义Behavior
使用请查看: