1、作为顶层布局
2、调度协调子布局
CoordinatorLayout使用新的思路通过协调调度子布局的形式实现触摸影响布局的形式产生动画效果。CoordinatorLayout使用的时候通常和
AppBarLayout搭配使用。
在AppBarLayout里面的View,通过app:layout_scrollFlags属性来控制滚动时候的表现,其中有4种Flag的类型:
- scroll: 所有想滚动出屏幕的view都需要设置这个flag,没有设置这个flag的view将被固定在屏幕顶部。例如,TabLayout 没有设置这个值,将会停留在屏幕顶部。
- enterAlways: 设置这个flag时,向下的滚动都会导致该view变为可见,启用快速“返回模式”。
- enterAlwaysCollapsed: 这个flag定义的是何时进入(已经消失之后何时再次显示)。当你的视图已经设置minHeight属性又使用此标志时,你的视图只能在到达这个最小高度的时候开始显示,只有当滚动视图到达顶部时才扩大到完整高度。
- exitUntilCollapsed: 当你定义了一个minHeight,这个view将在滚动到达这个最小高度的时候消失。
使用CoordinatorLayout需要在Gradle加入Support Design Library,例如:
compile 'com.android.support:design:22.2.1'
CoordinatorLayout实现了多种Material Design中提到的滚动效果。目前这个框架提供了几种不用写动画代码就能工作的方法,这些效果包括:
一、CoordinatorLayout与FloatingActionButton让浮动操作按钮上下滑动,为Snackbar留出空间
FloatingActionButton是最简单的使用CoordinatorLayout的例子,FloatingActionButton默认使用FloatingActionButton.Behavior。
CoordinatorLayout可以用来配合浮动操作按钮的 layout_anchor 和 layout_gravity属性创造出浮动效果。
只要使用CoordinatorLayout作为基本布局,将自动产生向上移动的动画。浮动操作按钮有一个 默认的 behavior来检测Snackbar的添加并让按钮在Snackbar之上呈现上移与Snackbar等高的动画。
当Snackbar在显示的时候,往往出现在屏幕的底部。为了给Snackbar留出空间,浮动操作按钮需要向上移动。
定义布局文件:<?xml version="1.0" encoding="utf-8"?>CoordinatorLayout作为“super-powered FrameLayout”,设置子视图的 android:layout_gravity属性控制位置。
<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=".activity.MainActivity1">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
MainActivity.java如下:
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main1);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab_main1);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "FAB", Snackbar.LENGTH_LONG)
.setAction("cancel", new View.OnClickListener() {
@Override
public void onClick(View v) {
//这里的单击事件代表点击消除Action后的响应事件
}
})
.show();
}
});
}
效果如下:
二、CoordinatorLayout与AppBarLayout
<?xml version="1.0" encoding="utf-8"?>当CoordinatorLayout发现RecyclerView中定义了这个属性,它会搜索自己所包含的其他view,看看是否有设置了app:layout_scrollFlags属性与这个 behavior相关联。AppBarLayout.ScrollingViewBehavior描述了RecyclerView与 AppBarLayout之间的依赖关系。RecyclerView的任意滚动事件都将触发AppBarLayout或者AppBarLayout里面 view的改变。
<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"
tools:context=".activity.MainActivity2">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_main2"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycle_main2"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_main2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
<android.support.design.widget.AppBarLayoutapp:layout_scrollFlags属性里面必须至少启用scroll这个flag,这样这个view才会滚动出屏幕,否则它将一直固定在顶部。
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_main2"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:layout_scrollFlags="scroll|enterAlways"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.AppBarLayout>
@Override效果如下:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar_main2);
setSupportActionBar(toolbar);
RecyclerView recyclerView = (RecyclerView) findViewById(R.id.recycle_main2);
LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
recyclerView.setLayoutManager(linearLayoutManager);
String[] titles = new String[20];
for (int i = 0; i < 20; i++)
titles[i] = "item " + i;
mAdapter=new RecyclerViewAdapter(this,titles);
recyclerView.setAdapter(mAdapter);
FloatingActionButton fab = (FloatingActionButton) findViewById(R.id.fab_main2);
fab.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "FAB", Snackbar.LENGTH_LONG)
.setAction("cancel", new View.OnClickListener() {
@Override
public void onClick(View v) {
//这里的单击事件代表点击消除Action后的响应事件
}
})
.show();
}
});
}
2.2 AppBarLayout嵌套TabLayout
support library包含了一个特殊的字符串资源@string/appbar_scrolling_view_behavior,它和AppBarLayout.ScrollingViewBehavior相匹配,用来通知AppBarLayout 这个特殊的view何时发生了滚动事件,这个behavior需要设置在触发事件(滚动)的view之上。而AppBarLayout里面定义的view只要设置了app:layout_scrollFlags属性,就可以在滚动事件发生的时候被触发。同时注意:根据官方的谷歌文档,AppBarLayout目前必须是第一个嵌套在CoordinatorLayout里面的子view。
<?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"
tools:context=".activity.MainActivity">
<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"
android:background="?attr/colorPrimary"
app:popupTheme="@style/AppTheme.PopupOverlay"
app:layout_scrollFlags="scroll|enterAlways"/>
<android.support.design.widget.TabLayout
android:id="@+id/tabs"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</android.support.design.widget.AppBarLayout>
<android.support.v4.view.ViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
2.3 AppBarLayout嵌套CollapsingToolbarLayout
<?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"
tools:context=".activity.MainActivity4">
<android.support.design.widget.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
<android.support.design.widget.CollapsingToolbarLayout
android:id="@+id/collapsing_toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fitsSystemWindows="true"
app:contentScrim="?attr/colorPrimary"
app:expandedTitleMarginEnd="64dp"
app:expandedTitleMarginStart="48dp"
app:layout_scrollFlags="scroll|exitUntilCollapsed">
<ImageView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:fitsSystemWindows="true"
android:scaleType="centerCrop"
android:src="@mipmap/smile"
app:layout_collapseMode="parallax" />
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar_main4"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
app:layout_scrollFlags="scroll|enterAlways"
app:layout_collapseMode="pin"
app:popupTheme="@style/ThemeOverlay.AppCompat.Light" />
</android.support.design.widget.CollapsingToolbarLayout>
</android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/recycle_main4"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior="@string/appbar_scrolling_view_behavior" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab_main4"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:src="@android:drawable/ic_dialog_email" />
</android.support.design.widget.CoordinatorLayout>
现在效果就成了:
+为了制造出这种效果,我们添加一个定义了app:layout_collapseMode="parallax" 属性的ImageView.
这种效果在详情页面用的较多,展示个性化内容,图像有强烈的吸引力。这个效果重点使用了CollapsingToolbarLayout 。
CollapsingToolbarLayout 提供以下属性和方法使用:
1. Collapsing title:ToolBar的标题,当CollapsingToolbarLayout全屏没有折叠时,title显示的是大字体,在折叠的过程中,title不断变小到一定大小的效果。通常,我们都是设置Toolbar的title,而现在,我们需要把title设置在CollapsingToolBarLayout上,而不是Toolbar。你可以调用setTitle(CharSequence)方法设置title。
2. Content scrim:ToolBar被折叠到顶部固定时候的背景,你可以调用setContentScrim(Drawable)方法改变背景或者 在属性中使用 app:contentScrim=”?attr/colorPrimary”来改变背景。
3. Status bar scrim:状态栏的背景,调用方法setStatusBarScrim(Drawable)。还没研究明白,不过这个只能在Android5.0以上系统有效果。
4. Parallax scrolling children:CollapsingToolbarLayout滑动时,子视图的视觉差,可以通过属性 app:layout_collapseParallaxMultiplier=”0.6”改变。值de的范围[0.0,1.0],值越大视察越大。
5. CollapseMode :子视图的折叠模式,在子视图设置,有两种“pin”:固定模式,在折叠的时候最后固定在顶端;“parallax”:视差模式,在折叠的时候会有个视差 折叠的效果。我们可以在布局中使用属性app:layout_collapseMode=”parallax”来改变。
三、自定义Behavior
publicbooleanlayoutDependsOn(CoordinatorLayout parent, View child, View dependency)
publicbooleanonDependentViewChanged(CoordinatorLayout parent, View child, View dependency)
public class CustomBehavior<V extends View> extends CoordinatorLayout.Behavior<V> {在上面这段代码中使用了范型,此时CustomBehavior可以被添加到任何View上,如果希望CustomBehavior只被添加到特定的View子类上,可以采用如下写法:
public CustomBehavior(Context context, AttributeSet attrs) {
super(context, attrs);
}
}
publicclassCustomBehaviorextendsCoordinatorLayout.Behavior<FloatingActionButton>
另外在Behavior的使用中,可以使用Behavior.setTag()/Behavior.getTag()来保存临时性的变量,另外也可以使用onSaveInstanceState()/onRestoreInstanceState()进行数据保存。善用这些方法可以让Behavior更具状态性。
添加Behavior
CustomBehavior
customBehavior = new
CustomBehavior
();
CoordinatorLayout.LayoutParams params = (CoordinatorLayout.LayoutParams) yourView.getLayoutParams();params.setBehavior(customBehavior);
<FrameLayout
android:layout_height=”wrap_content”
android:layout_width=”match_parent”
app:layout_behavior=”.CustomBehavior” />
@CoordinatorLayout.DefaultBehavior(CustomBehavior.class)
publicclassMyFloatingActionButton extendsFloatingActionButton{
}
使用这种方式添加的Behavior被设置成了DefaultBehavior,如果这时在Xml中使用layout_behavior的话,这个DefaultBehavior会被覆盖。
因为个人能力有限,对CoordinatorLayout的介绍就这么多吧,希望各位大神能不吝赐教
源代码
参考: