欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

使用CoordinatorLayout打造各种炫酷的效果

程序员文章站 2022-12-21 19:02:55
"使用CoordinatorLayout打造各种炫酷的效果" "自定义Behavior —— 仿知乎,FloatActionButton隐藏与展示" "NestedScrolling 机制深入解析" " 一步步带你读懂 CoordinatorLayout 源码" "自定义 Behavior 仿新浪微 ......

使用coordinatorlayout打造各种炫酷的效果

自定义behavior —— 仿知乎,floatactionbutton隐藏与展示

nestedscrolling 机制深入解析

一步步带你读懂 coordinatorlayout 源码

自定义 behavior -仿新浪微博发现页的实现

viewpager,scrollview 嵌套viewpager滑动冲突解决

自定义 behavior - 完美仿 qq 浏览器首页,美团商家详情页


coordinatorlayout简介

coordinatorlayout是在 google io/15 大会发布的,遵循material 风格,包含在 support library中,结合appbarlayout, collapsingtoolbarlayout等 可 产生各种炫酷的效果

coordinatorlayout简介通常用来 干什么

google官方地址

coordinatorlayout is intended for two primary use cases:

as a top-level application decor or chrome layout

as a container for a specific interaction with one or more child views

简单来说就是

  • 作为最上层的view
  • 作为一个 容器与一个或者多个子view进行交互

下面我们一起先来看一下我们实现的效果图

动态图

结合toolbar

使用CoordinatorLayout打造各种炫酷的效果

结合viewpager

使用CoordinatorLayout打造各种炫酷的效果

结合viewpager的视觉特差

使用CoordinatorLayout打造各种炫酷的效果


appbarlayout

它是继承与linearlayout的,默认 的 方向 是vertical

使用CoordinatorLayout打造各种炫酷的效果

类型 说明
int scroll_flag_enter_always when entering (scrolling on screen) the view will scroll on any downwards scroll event, regardless of whether the scrolling view is also scrolling.
int scroll_flag_enter_always_collapsed an additional flag for 'enteralways' which modifies the returning view to only initially scroll back to it's collapsed height.
int scroll_flag_exit_until_collapsed when exiting (scrolling off screen) the view will be scrolled until it is 'collapsed'.
int scroll_flag_scroll the view will be scroll in direct relation to scroll events.
int scroll_flag_snap upon a scroll ending, if the view is only partially visible then it will be snapped and scrolled to it's closest edge.
类型 说明
int scroll_flag_enter_always w((entering) / (scrolling on screen))下拉的时候,这个view也会跟着滑出。
int scroll_flag_enter_always_collapsed 另一种enteralways,但是只显示折叠后的高度。
int scroll_flag_exit_until_collapsed ((exiting) / (scrolling off screen))上拉的时候,这个view会跟着滑动直到折叠。
int scroll_flag_scroll 这个view将会响应scroll事件
int scroll_flag_snap 在scroll滑动事件结束以前 ,如果这个view部分可见,那么这个view会停在最接近当前view的位置

我们可以通过两种 方法设置这个flag

  • 方法一
 setscrollflags(int) 
  • 方法二
 app:layout_scrollflags="scroll|enteralways"

注意事项

appbarlayout必须作为coordinatorlayout的直接子view,否则它的大部分功能将不会生效,如layout_scrollflags等。

首先我们先来看一下我们 效果图一是怎样实现的

代码

<android.support.design.widget.coordinatorlayout
    android:id="@+id/main_content"
    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:id="@+id/appbar"
        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"
            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/recyclerview"
        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="end|bottom"
        android:layout_margin="15dp"
        android:src="@drawable/add_2"/>

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

思路 分析

使用CoordinatorLayout打造各种炫酷的效果

从图中我们可以知道 layout_scrollflags="scroll|enteralways,
前面已经说到layout_scrollflags=scroll的时候,这个view会 跟着 滚动 事件响应,
layout_scrollflags=“enteralways”的时候 这个view会响应下拉事件
所以呈现出来的结果应该是我们在上拉的时候toolbar 会隐藏,下拉的时候toolbar会出来

那如果当我们的toolbar 等于 app:layout_scrollflags="scroll|snap"的时候 ,
layout_scrollflags=scroll的时候,这个view会 跟着 滚动 事件响应,
layout_scrollflags=“snap”的时候 在scroll滑动事件结束以前 ,如果这个view部分可见,那么这个view会停在最接近当前view的位置。
综上呈现的效果如下,代码见toolbarsamplesnar的布局文件

使用CoordinatorLayout打造各种炫酷的效果

结合viewpager

布局代码如下

<android.support.design.widget.coordinatorlayout
    android:id="@+id/main_content"
    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="250dp">


        <imageview android:layout_width="match_parent"
                   android:layout_height="200dp"
                   android:background="?attr/colorprimary"
                   android:scaletype="fitxy"
                   android:src="@drawable/tangyan"
                   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:layout_alignparentbottom="true"
            android:background="?attr/colorprimary"
            app:tabindicatorcolor="@color/coloraccent"
            app:tabindicatorheight="4dp"
            app:tabselectedtextcolor="#000"
            app:tabtextcolor="#fff"/>

    </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="end|bottom"
        android:layout_margin="15dp"
        android:src="@drawable/add_2"/>

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

思路分析

使用CoordinatorLayout打造各种炫酷的效果

其实相对于前 一个例子,只是把 摆放recyclerview 的位置替换成viewpager而已,为了有页面导航器的效果,再使用 tablayout而已,而tablayout 在我们滑动的时候最终会停靠在 最顶部,是因为我们没有设置其layout_scrollflags,即tablayout是静态的

运行以后,即可看到以下的结果

使用CoordinatorLayout打造各种炫酷的效果

下面我们一起来看一下 tablayout是怎样结合viewpager直线 导航器的效果的

代码注释 里面已经解释地很清楚了 ,这里我就不解释了

public class viewpagersample extends appcompatactivity {

    viewpager mviewpager;
    list<fragment> mfragments;

    string[] mtitles = new string[]{
            "主页", "微博", "相册"
    };
    private tablayout mtablayout;

    @override
    protected void oncreate(bundle savedinstancestate) {
        super.oncreate(savedinstancestate);
        setcontentview(r.layout.activity_third);
        // 第一步,初始化viewpager和tablayout
        mviewpager = (viewpager) findviewbyid(r.id.viewpager);
        mtablayout = (tablayout) findviewbyid(r.id.tabs);
        setupviewpager();
    }

    private void setupviewpager() {

        mfragments = new arraylist<>();
        for (int i = 0; i < mtitles.length; i++) {
            listfragment listfragment = listfragment.newinstance(mtitles[i]);
            mfragments.add(listfragment);
        }
        // 第二步:为viewpager设置适配器
        basefragmentadapter adapter =
                new basefragmentadapter(getsupportfragmentmanager(), mfragments, mtitles);

        mviewpager.setadapter(adapter);
        //  第三步:将viewpager与tablelayout 绑定在一起
        mtablayout.setupwithviewpager(mviewpager);
    }


}

如果我们想更改indicator的相关样式,我们可以在布局文件里面使用

<android.support.design.widget.tablayout
    android:id="@+id/tabs"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_alignparentbottom="true"
    android:background="?attr/colorprimary"
    app:tabindicatorcolor="@color/coloraccent"
    app:tabindicatorheight="4dp"
    app:tabselectedtextcolor="#000"
    app:tabtextcolor="#fff"/>

如果你不想使用google 帮我们 封装好的控件的话,你也可以自己自定义一个控件,你可以参考我的这一篇博客


在看例子结合viewpager的视觉特差之前 ,我们需要先了解collapsingtoolbarlayout这个控件

collapsingtoolbarlayout

使用CoordinatorLayout打造各种炫酷的效果

collapsingtoolbarlayout继承与framelayout,官网地址,请自备*。

简单来说 ,collapsingtoolbarlayout是工具栏的包装器,它通常作为appbarlayout的孩子。主要实现以下功能

  • collapsing title(可以折叠 的 标题 )
  • content scrim(内容装饰),当我们滑动的位置 到达一定阀值的时候,内容 装饰将会被显示或者隐藏
  • status bar scrim(状态栏布)
  • parallax scrolling children,滑动的时候孩子呈现视觉特差效果
  • pinned position children,固定位置的 孩子

下面我们一起来看一下几个常量

常量 解释说明
int collapse_mode_off the view will act as normal with no collapsing behavior.(这个 view将会 呈现正常的结果,不会表现出折叠效果)
int collapse_mode_parallax the view will scroll in a parallax fashion. see setparallaxmultiplier(float) to change the multiplier used.(在滑动的时候这个view 会呈现 出 视觉特差效果 )
int collapse_mode_pin the view will pin in place until it reaches the bottom of the collapsingtoolbarlayout.(当这个view到达 collapsingtoolbarlayout的底部的时候,这个view 将会被放置,即代替整个collapsingtoolbarlayout)

我们有两种方法可以设置这个常量,

方法一:在代码中使用这个方法

setcollapsemode(int collapsemode)

方法 二:在布局文件中使用自定义属性

app:layout_collapsemode="pin"

到此 ,collapsingtoolbarlayout的一些重要属性已经讲解完毕,下面我们一起来看一下我们是怎样结合viewpager实现视差效果的


结合viewpager的视觉特差

布局代码

<?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"
    android:background="@android:color/background_light"
    android:fitssystemwindows="true"
>

    <android.support.design.widget.appbarlayout
        android:id="@+id/main.appbar"
        android:layout_width="match_parent"
        android:layout_height="300dp"
        android:fitssystemwindows="true"
        android:theme="@style/themeoverlay.appcompat.dark.actionbar"
    >

        <android.support.design.widget.collapsingtoolbarlayout
            android:id="@+id/main.collapsing"
            android:layout_width="match_parent"
            android:layout_height="250dp"
            android:fitssystemwindows="true"
            app:contentscrim="?attr/colorprimary"
            app:expandedtitlemarginend="64dp"
            app:expandedtitlemarginstart="48dp"
            app:layout_scrollflags="scroll|exituntilcollapsed"
        >

            <imageview
                android:id="@+id/main.backdrop"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:fitssystemwindows="true"
                android:scaletype="centercrop"
                android:src="@drawable/tangyan"
                app:layout_collapsemode="parallax"
            />

            <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/themeoverlay.appcompat.light"
            />
        </android.support.design.widget.collapsingtoolbarlayout>

        <android.support.design.widget.tablayout
            android:id="@+id/tabs"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_alignparentbottom="true"
            android:background="?attr/colorprimary"
            app:tabindicatorcolor="@color/coloraccent"
            app:tabindicatorheight="4dp"
            app:tabselectedtextcolor="#000"
            app:tabtextcolor="#fff"/>
    </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.v4.view.viewpager>


    <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="15dp"
        android:src="@drawable/add_2"/>

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

效果图如下

使用CoordinatorLayout打造各种炫酷的效果

思路解析

使用CoordinatorLayout打造各种炫酷的效果

  • 结构图如图片所示,先说明collapsingtoolbarlayout的变化

    collapsingtoolbarlayout里面 包含imageview 和toolbar,imageview的app:layout_collapsemode="parallax",表示视差效果,toolbar的 app:layout_collapsemode="pin",当这个toobar到达 collapsingtoolbarlayout的底部的时候,会代替整个collapsingtoolbarlayout显示

  • 接着说明tablayout的变化

    从前面的描述我们已经知道当 没有指定app:layout_scrollflags的时候,最终tablayout会静止,不会随着滑动的 时候消失不见

拓展

如果我们仅仅 改变collapsingtoolbarlayout的app:layout_scrollflags="scroll|exituntilcollapsed|snap"的时候,其它代码不变,运行以后,我们将可以看到如下效果图

使用CoordinatorLayout打造各种炫酷的效果


总结

这篇博客主要讲解了coordinatorlayout,appbarlayout,collapsingtoolbarlayout的一些相关属性。

  • 对于appbarlayout,我们主要 讲解了这个属性app:layout_scrollflags,设置不同 的属性我们可以在滚动的时候显示不同 的效果
  • 对于collapsingtoolbarlayout,我们主要讲解了app:layout_collapsemode这个属性,设置不同的值,我们可以让其子view呈现不同的 炫酷效果,如parallax和pin等

coordinatorlayout的相关用法还有很多,有兴趣 了解的请自行阅读: 官方文档地址


题外话

coordinatorlayout这个控件真的很强大,使用它可以实现各种炫酷的效果,简化了开发者的许多工作,有能力的话可以去研究一下源码 ,看是怎样实现的?

参考文章:android-[译]掌握coordinatorlayout

源码下载地址:https://github.com/gdutxiaoxu/coordinatorlayoutexample.git

欢迎大家关注我的微信公众号号 stormjun949(徐公码字),即可关注。 目前专注于 android 开发,主要分享 android开发相关知识和一些相关的优秀文章,包括个人总结,职场经验等。
使用CoordinatorLayout打造各种炫酷的效果