【译】Android CoordinatorLayout 简介

hello world

本篇blog为译文,原文地址为:INTRODUCTION TO COORDINATOR LAYOUT ON ANDROID

初次翻译,请多包涵,谢谢。

在2015年的谷歌开发者大会上,谷歌引入了Android Design Support Library(后面简称ADSL)来帮助码农在app中使用material design。ADSL中包含了一些非常重要的material design构建模块,并且兼容API 7及更高版本。点击查看更详细的ADSL信息..要翻墙..

初探CoordinatorLayout

ADSL引入的众多模块中,最有意思的是一个新的更强大的FrameLayout——CoordinatorLayout。从Layout的名字可以看出,CoordinatorLayout强大之处在于可以处理各子view之间的相互依赖关系。

CoordinatorLayout的用法非常简单,你要做的仅仅是将各个view放到CoordinatorLayout里面。让我们看个简单的demo:CoordinatorLayout中包含一个可以触发Snackbar的Floating Action Button。

  • 首先,在gradle里面加入ASDL依赖
    compile 'com.android.support:design:22.2.0'

  • 然后创建一个简单的layout文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.design.widget.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
android:src="@drawable/ic_done" />
</android.support.design.widget.CoordinatorLayout>
  • 接着是创建Activity
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.fab).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
Snackbar.make(view, "Hello Snackbar", Snackbar.LENGTH_LONG).show();
}
});
}
}
  • Demo展示

    很酷炫,对不对!!!

但是如果是使用第三方实现的FAB会怎样呢?让我们试试用“别人的”开源项目会产生怎样的效果

  • 首先在gradle中引入
    compile 'com.getbase:floatingactionbutton:1.9.1'

  • 然后修改布局文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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">
<com.getbase.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
app:fab_icon="@drawable/ic_done" />
</android.support.design.widget.CoordinatorLayout>
  • duang~duang~duang~

    被遮住了有木有。。CoordinatorLayout为啥子没有起作用!?

那是因为开源的FAB里没有实现CoordinatorLayout.Behavior。怎么办?等着某人给加上去呗,或者我们自己给加上去!!

让view知道该做什么

你不需要对view本身进行任何修改就可以加上你想要的行为或者更改view的默认行为,这正是这套框架的魅力所在。接下来我们要演示怎样让FAB知道该怎样动起来。

  • 首先,我们需要继承Behavior
    public class FloatingActionButtonBehavior extends CoordinatorLayout.Behavior<FloatingActionButton>
    为了能够通过XML创建这个View,我们需要添加一个包含Context和AttributeSet参数的构造函数。
    public FloatingActionButtonBehavior(Context context, AttributeSet attrs) {}

  • 接着覆盖layoutDependsOn()方法,如果我们想要监听其他view的变化就必须在该方法中返回true。在本例中我们只需要监听Snackbar的变化。

    1
    2
    3
    4
    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
    return dependency instanceof SnackbarLayout;
    }
  • 现在到了关键部分,onDependentViewChanged在被依赖的view每次发生变化时都会被调用,我们可以在该方法中获取Snackbar的状态。我们的目标是在Snackbar向上出现的同时向上移动FAB。所以就需要根据Snackbar的高度转换FAB的Y坐标。在Snackbar渐入动画开始时,Snackbar的Y轴偏移量就是Snackbar的高度,用Snackbar的Y轴偏移量减去Snackbar的高度就得到FAB在Y方向应该偏移的量。根据文档如果在该方法中view的位置发生了变化,该方法的应该返回true。

1
2
3
4
5
6
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, FloatingActionButton child, View dependency) {
float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
child.setTranslationY(translationY);
return true;
}
  • 最后一步是在xml中告知CoordinatorLayout该view使用FloatingActionButtonBehavior:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?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">
<com.getbase.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="end|bottom"
android:layout_margin="16dp"
app:layout_behavior="com.getbase.coordinatorlayoutdemo.FloatingActionButtonBehavior"
app:fab_icon="@drawable/ic_done" />
</android.support.design.widget.CoordinatorLayout>
  • 最后看看效果吧!

如果想要给你的view添加一个默认的behavior,你只需在view里添加DefaultBehavior注解并加上自定义Behavior的路径。
@DefaultBehavior(MyBehavior.class)

本篇blog包含代码都在github
Happy coding!