说说Android CoordinatorLayout

5.0之后的Android系统,google推出了自己的移动端设计规范,Material Design,同时sdk包中也加入了support.design包,加入了很多符合md风格的组件。这里主要讲解一下CoordinatorLayout这个布局和它的使用。

什么是CoordinatorLayout

​ 正如它的名字,这个布局是用来协调2个控件之间的联动。我们使用一个图片来说明这个布局的最终效果。

​ 可以发现地下的视图滑动上去之后上面图片所在的区域会被折叠,然后会有一个Toolbar悬停在顶部。

​ 下面我来实现以下这个效果

​ 引入design包里面的组件:

compile 'com.android.support:design:25.3.1'

​ 新建一个Activity和布局文件

​ 布局文件如下:

<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.design.widget.AppBarLayout
        android:layout_width="match_parent"
        android:layout_height="200dp">
        <android.support.design.widget.CollapsingToolbarLayout
            android:id="@+id/collapsingToolbarLayout_1"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:contentScrim="@color/colorPrimary"
            app:layout_scrollFlags="exitUntilCollapsed|scroll|enterAlways"
            app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
            >

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/head_img"
                app:layout_collapseMode="parallax"
                android:scaleType="centerCrop"
                />

            <android.support.v7.widget.Toolbar
                android:layout_width="match_parent"
                android:layout_height="?attr/actionBarSize"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/ThemeOverlay.AppCompat.Light"
                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v7.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior" />

</android.support.design.widget.CoordinatorLayout>

这个布局的分析如下:

最外层使用CoordinatorLayout,顶部的折叠部分使用AppBarLayout,在AppBarLayout中我们加入了一个图片和Toolbar,图片和Toolbar需要包含在一个CollapsingToolbarLayout里面。

下方是一个用来滑动的RecyclerView。

分析一下一些默认属性的作用:

CollapsingToolbarLayout

app:contentScrim 折叠后Toolbar的颜色

app:layout_scrollFlags 滑动折叠的五种效果

  • scroll Child View 伴随着滚动事件而滚出或滚进屏幕。注意两点:第一点,如果使用了其他值,必定要使用这个值才能起作用;第二点:如果在这个child View前面的任何其他Child View没有设置这个值,那么这个Child View的设置将失去作用。
  • enterAlways 滚动优先级。比较scroll和scroll|enterAlways, 设置该属性后,向下滚动的时候,前者优先滚动可滚动的组件,后者优先滚动child view。
  • enterAlwaysCollapsed enterAlways的附加值。这里涉及到Child View的高度和最小高度,向下滚动时,Child View先向下滚动最小高度值,然后Scrolling View开始滚动,到达边界时,Child View再向下滚动,直至显示完全。
  • exitUntilCollapsed child view不完全退出屏幕,child view向上滚动停住以后再往上滚动滚动组件。例如折叠后Toolbar不退出屏幕,悬停在上方,然后RecyclerView的视图向上滑动。
  • snap child view要么显示要么全部退出屏幕。
child view中的

app:layout_collapseMode 折叠的模式,有三种。其中none表示没有效果。其余2个分别是

  • pin 固定模式,折叠后固定在顶端。
  • parallax 视差模式,在折叠的时候会有个视差折叠的效果。

####### 可滚动的控件

app:layout_behavior 行为,指定在scroll view上面的。这里我们设置为

app:layout_behavior="@string/appbar_scrolling_view_behavior"

这个指的是AppBarLayout中的内部类ScrollingViewBehavior,这个用来指定RecyclerView和AppBarLayout之间的联动。查看源码

@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
    // We depend on any AppBarLayouts
    return dependency instanceof AppBarLayout;
}

@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child,
View dependency) {
    offsetChildAsNeeded(parent, child, dependency);
    return false;
}

这段代码的含义分别是指定滑动行为根据AppBarLayout决定。在onDependentViewChanged方法中我们指定了移动的方式。具体代码在这不赘述。

这个时候我们的基本效果就实现了。可见这个MD控件的强大。当然它的具体实现也是很复杂的。

常见问题

同时我们可以发现Toolbar的行为是根据CollapsingToolbarLayout来控制的。

设置Toolbar的title,会发现效果没有达到预期。title不会随着滑动缩放。

那么问题来了,我们如何设置Toolbar的标题呢?

Toolbar的标题我们可以如下设置:

mCollapsingToolbarLayout.setTitle("标题");
setSupportActionBar(mToolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        finish();
    }
});

现在问题又来了,正常我们不设置的时候,会发现有一个md规范控件自带的效果,标题会在滚动过程中上下移动并且缩放大小的效果。有时候我们并不想把标题显示在下发,这个时候应该怎么办呢?

可以在style文件中设置

<style name="collapsing_toolbar_text_size">
    <item name="android:textSize">0sp</item>
</style>

在Activity中设置

mCollapsingToolbarLayout
  .setExpandedTitleTextAppearance(R.style.collapsing_toolbar_text_size);

这句代码的含义是设置滑动后的标题字体大小,我们设置为0sp,就不会有任何显示了。

附上最后Activity里面的代码,也可以参考我在github上的demo代码

public class CoordinatorTestActivity extends AppCompatActivity {
    private RecyclerView recyclerView;
    private List<String> data = new ArrayList<>();
    private CollapsingToolbarLayout collapsingToolbarLayout;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.act_coordinator);
        recyclerView = (RecyclerView) findViewById(R.id.recycler_view);
        initData();
        MyAdapter adapter = new MyAdapter(this,data);
        recyclerView.setLayoutManager(new LinearLayoutManager(this));
        recyclerView.setAdapter(adapter);
        collapsingToolbarLayout = (CollapsingToolbarLayout) findViewById(R.id.collapsingToolbarLayout_1);
        collapsingToolbarLayout.setTitle("标题");
        collapsingToolbarLayout.setExpandedTitleTextAppearance(R.style.collapsing_toolbar_text_size);
    }

    private void initData() {
        for (int i = 0;i < 20;i++) {
            data.add("str"+i);
        }
    }

    class MyAdapter extends RecyclerView.Adapter<MyAdapter.MyHolder> {
        private Context mContext;
        private List<String> mData;

        public MyAdapter(Context context, List<String> data) {
            mContext = context;
            mData = data;
        }

        @Override
        public MyHolder onCreateViewHolder(ViewGroup parent, int viewType) {
            return new MyHolder(LayoutInflater.from(mContext).inflate(android.R.layout.simple_list_item_1, parent, false));
        }

        @Override
        public void onBindViewHolder(MyHolder holder, int position) {
            String text = mData.get(position);
            holder.tv.setText(text);
        }

        @Override
        public int getItemCount() {
            return mData.size();
        }

        class MyHolder extends RecyclerView.ViewHolder{
            TextView tv;
            public MyHolder(View itemView) {
                super(itemView);
                tv = (TextView) itemView.findViewById(android.R.id.text1);
            }
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,716评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,558评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,431评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,127评论 0 209
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,511评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,692评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,915评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,664评论 0 202
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,412评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,616评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,105评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,424评论 2 254
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,098评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,096评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,869评论 0 197
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,748评论 2 276
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,641评论 2 271

推荐阅读更多精彩内容