Android开发Material DesignAndroid-CoordinatorLayout.……

android ui 学习系列 - 初识 Coordinator

2017-10-27  本文已影响140人  前行的乌龟

CoordinatorLayout是support.design包中的控件,它可以说是Design库中最重要的控件。

他提供了一种全新的布局玩法 - 折叠(关联),何为折叠,就是让一些指定控件的位置,形态随着指定的控件的变化而变化,最简单的例子,就是标题栏随着列表的滚动而显示或消失或这折叠,这是5.0添加的新特性,之前我们监听滚动列表的滚动状态也可以做到这个效果,但是代码会很耦合。这次 google 提供了这个 CoordinatorLayout 顶层容器,配合 Behavior 来封装解耦了这个需求,让我们编写相关业务代码更简单,同理效果也是更好。

本地 demo 地址: github


核心套路

我先说说 CoordinatorLayout 的核心套路,这里插一句是为了以后好找:


CoordinatorLayout 使用详细讲解

这里有2个概念:

Design 里面有默认的 Behavior 实现,就是一下这个 layout 组合:

<android.support.design.widget.CoordinatorLayout
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:fitsSystemWindows="true"
        android:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:fitsSystemWindows="true"
            app:contentScrim="?attr/colorPrimary"
            app:statusBarScrim="@color/colorAccent"
            app:titleEnabled="false"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <android.support.v7.widget.Toolbar  
                app:popupTheme="@style/AppTheme.PopupOverlay"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7"
                app:layout_collapseMode="pin"/>

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

    <android.support.v4.widget.NestedScrollView
        app:layout_behavior="@string/appbar_scrolling_view_behavior">
    </android.support.v4.widget.NestedScrollView>

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

就是上面这几个布局 CoordinatorLayout + AppBarLayout + CollapsingToolbarLayout + Toolbar + NestedScrollView

这里有2个角色划分:

   app:layout_behavior="@string/appbar_scrolling_view_behavior">

设置 layout_behavior 标记,就是设置发起滚动关联的事件源


系统默认提供的 Behavior

系统 activity 模板里的 ScrollingActivity ,使用的就是系统提供的 Behavior ,是我们学习 Behavior 的最好的初始资料,我们先来看这个


11111.gif

系统的 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="com.bloodcrown.croodnatorlayouttest2.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.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="com.bloodcrown.croodnatorlayouttest2.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>

    <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"/>

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

恩,这个布局精简过后,就是我们上面列的默认的 Behavior 实现Behavior 实现 layout 组合:

<android.support.design.widget.CoordinatorLayout>

    <android.support.design.widget.AppBarLayout>

        <android.support.design.widget.CollapsingToolbarLayout
            app:contentScrim="?attr/colorPrimary"
            app:statusBarScrim="?attr/colorPrimary"
            app:layout_scrollFlags="scroll|exitUntilCollapsed">

            <android.support.v7.widget.Toolbar  
                app:layout_collapseMode="pin"/>

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

    <android.support.v4.widget.NestedScrollView
        app:layout_behavior="@string/appbar_scrolling_view_behavior"/>

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

好了这里就是重点了,大家注意

先说说这几个布局的嵌套关系

然后呢,再来看看这几个布局的参数设置:

滚动布局设置参数:
app:layout_behavior="@string/appbar_scrolling_view_behavior"/>
AppBarLayout 的参数设置:

layout_scrollFlags,这是 AppBarLayout 的滚动模式设置,有5种值,给标题栏中需要滚动的部分设置,不设置的 view 不会参与滚动

CollapsingToolbarLayout 的参数设置:

contentScrim / statusBarScrim,这2个属性,是设置标题栏在折叠后的内容颜色和状态栏颜色

FloatingActionButton 的参数设置:

好了这些布局的关系和属性设置我们都了解了之后就可以自己来玩来,这里面可是大有可为的,咱们来好好玩玩


自由使用系统默认提供的 Behavior

我们不要局限在系统给我们提供的 ScrollActivity 的写法中,适当的变通还是可以有点啊,比如现在很常见的,标题栏中我们加一张图片进去做打底图,或者不用 toolBar ,自己封装组合 view 都是可以的,我们先来做下面这个样式的


ezgif.com-video-to-gif.gif

这个实现还是很简单的,我们先来看看 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:fitsSystemWindows="true"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.bloodcrown.croodnatorlayouttest2.FreeActivity1">

    <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"
        app:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="@color/colorAccent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:statusBarScrim="@color/colorAccent"
            app:titleEnabled="false">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                android:src="@mipmap/x001"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7"/>

            <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"
                app:title="">

                <!--<TextView-->
                    <!--android:layout_width="wrap_content"-->
                    <!--android:layout_height="wrap_content"-->
                    <!--android:layout_gravity="top|left"-->
                    <!--android:gravity="top|left"-->
                    <!--android:text="测试"/>-->

            </android.support.v7.widget.Toolbar>

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

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

    <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="com.bloodcrown.croodnatorlayouttest2.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>

    <android.support.design.widget.FloatingActionButton
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="@dimen/fab_margin"
        android:src="@mipmap/ic_launcher_round"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|right"/>

录屏时toolbar 里面的 textview 注释了,效果图里看不到,实际上还是能正常显示的,大家放心。

我们首先让系统状态烂透明,这样才能让图片实现顶置显示

public class FreeActivity1 extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_free1);

        intiStateView();
    }

    private void intiStateView() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
            layoutParams.flags = (layoutParams.flags | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

CollapsingToolbarLayout 折叠布局继承帧布局,我们在里面放什么view 都行,只要设置扯着模式就行,这里放入了一个 imageview,使用了0.7的折叠视差效果,和起点 app 小说详情页
的标题栏一样,滚动时收缩都是带视差效果的。

以下有2个注意点:

fitsSystemWindows 属性

在我们设置系统状态栏透明后,会造成 toolbar 占用系统状态栏的位置的问题,这时我们需要 设置android:fitsSystemWindows="true" 这个属性。这个 fitsSystemWindows 属性,要从跟布局一直设置到具体的填充系统状态烂的布局才行(在例子中是imageview 这个 view),有些麻烦。

我的xml 设置:

<android.support.design.widget.CoordinatorLayout
    android:fitsSystemWindows="true">

    <android.support.design.widget.AppBarLayout
        android:fitsSystemWindows="true">

        <android.support.design.widget.CollapsingToolbarLayout
            android:fitsSystemWindows="true">

            <ImageView
                android:fitsSystemWindows="true"/>

toolbar 占用系统状态栏的位置:这里把 toolbar 的颜色设置为黑色

Snip20171028_11.png
imageview

不知道大家注意没有,我们设置 android:fitsSystemWindows="true" 后,就是给 toolbar 内部添加了一个系统状态栏高度的 maggin,要是在标题栏在展开模式时 toolbar 没有自己的颜色设置的话,其实这个 fitsSystemWindows 写不写都行,写了toolbar 的内容会往下走一点,不写toolbar 的内容会正好卡在系统状态烂的下面,觉得贴的紧的话,自己加一个 padding 上去也可以的,具体的还是看需求,在这里把问题高清楚方便之后我们的具体使用

这张图是我们添加 fitsSystemWindows="true" 之后,toolbar 的位置在状态栏的下面,toolbar 黑色背景真丑,但是为了看看效果也是没办法的。这个 toolbar 里面的 textview 的位置设置的是 top|left,文字上面的 maggin和系统状态栏的高度其实是一样的。所以说设置 fitsSystemWindows 标记,就是给 toolbar 加了一个系统状态栏高度的 maggin

toolbar 的使用方式

toolbar的使用有2种:

具体取舍看具体需求把,我比较喜欢单纯当做 layout 来用,这样灵活。

toolbar和系统的 actionbar 关联 代码

 Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
 setSupportActionBar(toolbar);

搭配 TabLayout 使用

在页面的编写时常常会用到 TabLayout ,或是替代的开源库,这个我们应该怎么和我们上面的例子结合呢,为啥说这个呢,因为 appbarlayout 在折叠后,高度会是 toolbar 的高度,这时候 toolbar 的高度要适配 TabLayout 的高度才行,要不就会挤在一起


Snip20171028_15.png

那么我们怎么解决这个问题呢,看下面:

在xml中 TabLayout 和 Toolbar 同级,toolbar 的高度设置为 tollbar 本身的 height + TabLayout 的 height ,这种做法需要知道 TabLayout 和 Toolbar 的确切高度值。xml 里面要是height 没有确定值那就用代码计算一下再设置也行

 <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"
        app:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="@color/colorAccent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:statusBarScrim="@color/colorAccent"
            app:title=""
            app:titleEnabled="false">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                android:src="@mipmap/x001"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="90dp"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay"
                app:title="">

                <TextView
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="top|left"
                    android:gravity="top|left"
                    android:text="测试"
                    android:textSize="16sp"/>

            </android.support.v7.widget.Toolbar>

            <android.support.design.widget.TabLayout
                android:id="@+id/view_tab"
                android:layout_width="match_parent"
                android:layout_height="45dp"
                android:layout_gravity="bottom"
                android:gravity="center_vertical"></android.support.design.widget.TabLayout>

        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>
ezgif.com-video-to-gif.gif

为啥要特别说 tablayout 呢,因为上面我们要让 tablayout 站在背景图片中,参与折叠,要是不在背景图片就不要放到 CollapsingToolbarLayout 里面就好了,更省事。

这段是我 copy 过来的:


仿 bilibili 视频详情页

图我是 copy 过来的,放哔哩哔哩这个也算是经典学习类目之一了

828721-61defc66bb3e9fb8.gif

我录屏转换gif 太大了,特意压缩了下分辨率才能传上来,效果可能不是很好


ezgif.com-video-to-gif.gif

分析下思路:

基本需求和思路就是上面几条,前面的例子玩会了,我们搭建这个 bilibili 页面就会了,区别在于 toolbar 在折叠和展开时,显示不同的 view。

toolbar 定义不同的状态的 view

这个简单,这里我把 toolbar 作为 layout 使用,不可系统 actionbar 管理,里面定义2条 view ,一个显示,一个隐藏

<android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay"
                app:title="">

                <android.support.constraint.ConstraintLayout
                    android:id="@+id/appbar_show"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:visibility="visible">

                    <ImageView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:src="@drawable/ic_arrow_back_black_24dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintLeft_toLeftOf="parent"
                        app:layout_constraintTop_toTopOf="parent"/>

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="BiLiBiLi大讲堂开播啦"
                        android:textColor="@android:color/white"
                        android:textSize="22sp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintLeft_toLeftOf="parent"
                        app:layout_constraintRight_toRightOf="parent"
                        app:layout_constraintTop_toTopOf="parent"/>

                </android.support.constraint.ConstraintLayout>

                <android.support.constraint.ConstraintLayout
                    android:id="@+id/appbar_hint"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:visibility="gone">

                    <ImageView
                        android:id="@+id/appbar_hint_icon"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:src="@drawable/ic_play_circle_filled_black_24dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintHorizontal_chainStyle="packed"
                        app:layout_constraintLeft_toLeftOf="parent"
                        app:layout_constraintRight_toLeftOf="@+id/appbar_hint_name"
                        app:layout_constraintTop_toTopOf="parent"/>

                    <TextView
                        android:id="@+id/appbar_hint_name"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="10dp"
                        android:text="立即播放"
                        android:textColor="@android:color/white"
                        android:textSize="22sp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintLeft_toRightOf="@+id/appbar_hint_icon"
                        app:layout_constraintRight_toRightOf="parent"
                        app:layout_constraintTop_toTopOf="parent"/>

                </android.support.constraint.ConstraintLayout>
            </android.support.v7.widget.Toolbar>

可以看到我定义了 show 和 hint 2个 view,对于展开和折叠状态

监听 appbarlayout

CollapsingToolbarLayout 收缩布局本身没有监听函数,他也是监听 appbarlayout 实现动画的,这里我们也去监听 appbarlayout 的滚动变化,自己记录维护 appbarlayout 的展开和折叠状态值。

先定义 appbarlayout 的3种状态值

    // appbar展开状态
    public static final int STAET_EXPANDED = 1;
    // appbar折叠状态
    public static final int STAET_COLLAPSED = -1;
    // appbar中间状态
    public static final int STAET_ING = 0;

然后再去监听 appbarlayout 滚动变化

 mAppBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {

//                int totalScrollRange = appBarLayout.getTotalScrollRange();
//                Log.d("AAA", "total:" + totalScrollRange + "/Offset:" + verticalOffset);

                verticalOffset = Math.abs(verticalOffset);

                // 初始展开状态
                if (verticalOffset == 0) {
                    if (state != STAET_EXPANDED) {
                        // 是展开状态,重置标记为展开,显示 appbar 布局控件
                        state = STAET_EXPANDED;
                        appBar_show.setVisibility(View.VISIBLE);
                        appBar_hint.setVisibility(View.GONE);
                    }
                    return;
                }

                // 折叠状态
                if (verticalOffset >= appBarLayout.getTotalScrollRange()) {
                    if (state != STAET_COLLAPSED) {
                        // 是折叠状态,重置标记为折叠,显示 appbar 布局控件
                        state = STAET_COLLAPSED;
                        appBar_hint.setVisibility(View.VISIBLE);
                        appBar_show.setVisibility(View.GONE);
                    }
                    return;
                }

                // 中间状态
                if (state != STAET_ING) {
                    // 是中间状态,重置标记为ing,显示 appbar 布局控件
                    state = STAET_ING;
                    appBar_show.setVisibility(View.VISIBLE);
                    appBar_hint.setVisibility(View.GONE);
                }
            }
        });

这里面有几个注意点:

appbarlayout不再相应滚动事件

这个好做,现成的 api,只要让滚动 view 不再发射滚动事件就行了

 mFAB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (state == STAET_EXPANDED) {
                    if (state_scroll == SCROLL_ING) {
                        // 取消滚动控件的嵌套滚动,核心的就是这个函数了,大家注意啊
                        mScrollView.setNestedScrollingEnabled(false);
                        state_scroll = SCROLL_NO;
                    } else if (state_scroll == SCROLL_NO) {
                        mScrollView.setNestedScrollingEnabled(true);
                        state_scroll = SCROLL_ING;
                    }
                }
            }
        });

折叠状态切换到展开状态

这个页简单,现成的 api, setExpanded(true)

mPlayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (state == STAET_COLLAPSED) {
                    // 处于折叠状态时才能玩
                    mAppBar.setExpanded(true);
                    state = STAET_EXPANDED;
                }
            }
        });

完整代码:

<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.bloodcrown.croodnatorlayouttest2.FreeActivity1">

    <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"
        app:theme="@style/AppTheme.AppBarOverlay">

        <android.support.design.widget.CollapsingToolbarLayout
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:fitsSystemWindows="true"
            app:contentScrim="@color/colorAccent"
            app:layout_scrollFlags="scroll|exitUntilCollapsed"
            app:statusBarScrim="@color/colorAccent"
            app:title=""
            app:titleEnabled="false">

            <ImageView
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitsSystemWindows="true"
                android:scaleType="centerCrop"
                android:src="@mipmap/x001"
                app:layout_collapseMode="parallax"
                app:layout_collapseParallaxMultiplier="0.7"/>

            <android.support.v7.widget.Toolbar
                android:id="@+id/toolbar"
                android:layout_width="match_parent"
                android:layout_height="50dp"
                app:layout_collapseMode="pin"
                app:popupTheme="@style/AppTheme.PopupOverlay"
                app:title="">

                <android.support.constraint.ConstraintLayout
                    android:id="@+id/appbar_show"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:visibility="visible">

                    <ImageView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:src="@drawable/ic_arrow_back_black_24dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintLeft_toLeftOf="parent"
                        app:layout_constraintTop_toTopOf="parent"/>

                    <TextView
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:text="BiLiBiLi大讲堂开播啦"
                        android:textColor="@android:color/white"
                        android:textSize="22sp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintLeft_toLeftOf="parent"
                        app:layout_constraintRight_toRightOf="parent"
                        app:layout_constraintTop_toTopOf="parent"/>

                </android.support.constraint.ConstraintLayout>

                <android.support.constraint.ConstraintLayout
                    android:id="@+id/appbar_hint"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:gravity="center"
                    android:visibility="gone">

                    <ImageView
                        android:id="@+id/appbar_hint_icon"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:src="@drawable/ic_play_circle_filled_black_24dp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintHorizontal_chainStyle="packed"
                        app:layout_constraintLeft_toLeftOf="parent"
                        app:layout_constraintRight_toLeftOf="@+id/appbar_hint_name"
                        app:layout_constraintTop_toTopOf="parent"/>

                    <TextView
                        android:id="@+id/appbar_hint_name"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:layout_marginLeft="10dp"
                        android:text="立即播放"
                        android:textColor="@android:color/white"
                        android:textSize="22sp"
                        app:layout_constraintBottom_toBottomOf="parent"
                        app:layout_constraintLeft_toRightOf="@+id/appbar_hint_icon"
                        app:layout_constraintRight_toRightOf="parent"
                        app:layout_constraintTop_toTopOf="parent"/>

                </android.support.constraint.ConstraintLayout>
            </android.support.v7.widget.Toolbar>
        </android.support.design.widget.CollapsingToolbarLayout>
    </android.support.design.widget.AppBarLayout>

    <android.support.v4.widget.NestedScrollView
        android:id="@+id/view_nest"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_behavior="@string/appbar_scrolling_view_behavior"
        tools:context="com.bloodcrown.croodnatorlayouttest2.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>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/view_fab"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="@dimen/fab_margin"
        android:src="@drawable/ic_play_circle_filled_black_24dp"
        app:layout_anchor="@id/app_bar"
        app:layout_anchorGravity="bottom|right"/>

</android.support.design.widget.CoordinatorLayout>
public class BiliBiLiActivity extends AppCompatActivity {

    // appbar展开状态
    public static final int STAET_EXPANDED = 1;
    // appbar折叠状态
    public static final int STAET_COLLAPSED = -1;
    // appbar中间状态
    public static final int STAET_ING = 0;

    int state = 2;

    // appbar 响应滚动状态
    public static final int SCROLL_ING = -1;
    // appbar 不响应滚动状态
    public static final int SCROLL_NO = 0;

    int state_scroll = SCROLL_ING;


    View appBar_show;
    View appBar_hint;
    FloatingActionButton mFAB;
    AppBarLayout mAppBar;
    NestedScrollView mScrollView;
    View mPlayButton;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_bili_bi_li);

        intiStateView();

        appBar_show = findViewById(R.id.appbar_show);
        appBar_hint = findViewById(R.id.appbar_hint);
        mFAB = (FloatingActionButton) findViewById(R.id.view_fab);
        mAppBar = (AppBarLayout) findViewById(R.id.app_bar);
        mScrollView = (NestedScrollView) findViewById(R.id.view_nest);
        mPlayButton = findViewById(R.id.appbar_hint_name);

        mAppBar.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() {
            @Override
            public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) {

//                int totalScrollRange = appBarLayout.getTotalScrollRange();
//                Log.d("AAA", "total:" + totalScrollRange + "/Offset:" + verticalOffset);

                verticalOffset = Math.abs(verticalOffset);

                // 初始展开状态
                if (verticalOffset == 0) {
                    if (state != STAET_EXPANDED) {
                        // 是展开状态,重置标记为展开,显示 appbar 布局控件
                        state = STAET_EXPANDED;
                        appBar_show.setVisibility(View.VISIBLE);
                        appBar_hint.setVisibility(View.GONE);
                    }
                    return;
                }

                // 折叠状态
                if (verticalOffset >= appBarLayout.getTotalScrollRange()) {
                    if (state != STAET_COLLAPSED) {
                        // 是折叠状态,重置标记为折叠,显示 appbar 布局控件
                        state = STAET_COLLAPSED;
                        appBar_hint.setVisibility(View.VISIBLE);
                        appBar_show.setVisibility(View.GONE);
                    }
                    return;
                }

                // 中间状态
                if (state != STAET_ING) {
                    // 是中间状态,重置标记为ing,显示 appbar 布局控件
                    state = STAET_ING;
                    appBar_show.setVisibility(View.VISIBLE);
                    appBar_hint.setVisibility(View.GONE);
                }
            }
        });

        mFAB.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (state == STAET_EXPANDED) {
                    if (state_scroll == SCROLL_ING) {
                        // 取消滚动控件的嵌套滚动
                        mScrollView.setNestedScrollingEnabled(false);
                        state_scroll = SCROLL_NO;
                    } else if (state_scroll == SCROLL_NO) {
                        mScrollView.setNestedScrollingEnabled(true);
                        state_scroll = SCROLL_ING;
                    }
                }
            }
        });

        mPlayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (state == STAET_COLLAPSED) {
                    // 处于折叠状态时才能玩
                    mAppBar.setExpanded(true);
                    state = STAET_EXPANDED;
                }
            }
        });

    }

    private void intiStateView() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
            layoutParams.flags = (layoutParams.flags | WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
        }
    }

参考资料

上一篇 下一篇

猜你喜欢

热点阅读