CoordinatorLayout、AppBarLayout、 Toolbar、CollapsingToolbarLayout、NestedScrollView 综合使用,详细解析

这篇文章主要介绍CoordinatorLayout、AppBarLayout、 Toolbar、CollapsingToolbarLayout、NestedScrollView的使用。看上去很多,其实真的很简单。

我们先来看一下,使用这些控件最终实现的效果图,然后根据源码,逐一分析他所使用到的控件,及每个控件配置的属性.

这里写图片描述

完整代码下载地址

这里给出代码,主要体现这些控件的嵌套关系,让你有总体的认识。

<android.support.design.widget.CoordinatorLayout
...此处省略若干代码>
           <android.support.design.widget.AppBarLayout
             ...此处省略若干代码 >

              <android.support.design.widget.CollapsingToolbarLayout
                ...此处省略若干代码>

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


                <android.support.v7.widget.Toolbar
                    android:id="@+id/toolbar"
                    android:layout_width="match_parent"
                    android:layout_height="56dp"
                    app:layout_collapseMode="pin"
                    android:elevation="4dp"
                    />

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

        <android.support.v4.widget.NestedScrollView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:layout_behavior="@string/appbar_scrolling_view_behavior"
            >
           ...此处省略若干代码
        </android.support.v4.widget.NestedScrollView>
    </android.support.design.widget.CoordinatorLayout>

1、CoordinatorLayout

这个控件到底能做什么呢?从字面上意思是协调子View的,就是我们滑动(或其他操作)一个Layout,另一个Layout自动执行相应已经设定好的操作。看下图就明白了

这里写图片描述

蓝色的是一个自定义View,可跟随手指移动

黄色的是一个Button。

他们之间的运动关系:它们在竖直方向同步移动,在水平方向相反。

这个效果如果让你不用CoordinatorLayout去实现,应该没有任何问题,但是代码的耦合度应该非常大,你的代码必须要持有2个View的引用,然后在onTouchEvent里面做各种判断。如果我们想要实现的功能是,有更多的View要根据蓝色的View的移动相应作出响应,那么那就得在蓝色View的onTounchEvent里面针对其他的View处理各种逻辑。这耦合度未免太伤感了~

而CoordinatorLayout既然号称能帮我们协调子View的布局,我们接下来看看CoordinatorLayout如何实现~

CoordinatorLayout使用

在使用前,需要了解三个概念:

  • Dependency View (上图中的蓝色view)Child依赖的View
  • child View (上图中的黄色Button)CoordinatorLayout的子View,操作Dependency View 时,根据Behavior类,对child View自动执行相关操作
  • Behavior类,指定Child View的运动规则。自定义Behavior类,需要实现两个方法

简而言之,就是Dependency View发生了变化,那么Child View就要相应发生变化。
发生变化是具体发生什么变化呢?这里就要引入Behavior,Child发生变化的代码都是放在Behavior类里面。

怎么使用Behavior呢,首先,我们定义一个类,继承CoordinatorLayout.Behavior < T>,其中,泛型参数T是我们要执行动作的View类,也就是Child。然后就是去实现Behavior的两个方法:

/**
* 判断child的布局是否依赖dependency
*/
   @Override
 public boolean layoutDependsOn(CoordinatorLayout parent, T child, View dependency) {
    boolean rs;
    //根据逻辑判断rs的取值
    //返回false表示child不依赖dependency,ture表示依赖
    return rs;  
}

/**
* 当dependency发生改变时(位置、宽高等),执行这个函数
* 返回true表示child的位置或者是宽高要发生改变,否则就返回false
*/
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, T child, View dependency) {
     //child要执行的具体动作
        return true;
}

看一下这个示例中的Behavior是怎么实现的

public class MyBehavior extends CoordinatorLayout.Behavior<Button> {
    private int width;

    public MyBehavior(Context context, AttributeSet attrs) {
        super(context, attrs);
        DisplayMetrics display = context.getResources().getDisplayMetrics();
        width = display.widthPixels;
    }

    @Override
    public boolean layoutDependsOn(CoordinatorLayout parent, Button child, View dependency) {
        //如果dependency是TempView的实例,说明它就是我们所需要的Dependency
        return dependency instanceof TempView;
    }

    //每次dependency位置发生变化,都会执行onDependentViewChanged方法
    @Override
    public boolean onDependentViewChanged(CoordinatorLayout parent, Button btn, View dependency) {

        //根据dependency的位置,设置Button的位置

        int top = dependency.getTop();
        int left = dependency.getLeft();

        int x = width - left - btn.getWidth();
        int y = top;

        setPosition(btn, x, y);
        return true;
    }

    private void setPosition(View v, int x, int y) {
        CoordinatorLayout.MarginLayoutParams layoutParams = (CoordinatorLayout.MarginLayoutParams) v.getLayoutParams();
        layoutParams.leftMargin = x;
        layoutParams.topMargin = y;
        v.setLayoutParams(layoutParams);
    }


}

OK,现在我们定义好了跟随Dependency一直变化的动作(Behavior),接下来我们就要指定哪个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"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        app:layout_behavior="cn.xuexuan.newui.CoordinatorBehavior"/>


    <cn.xuexuan.newui.MoveView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="@color/colorAccent"
        />


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

至此,就可以实现上面动图的效果。

在最开始的那幅图中,在滑动时,自动改变AppBarLayout。你可能会想到,如果要实现图一的效果,那这个Behavior,肯定很难写啊。但是不用担心,android已经提供了这样的Behavior。来看一下面的这个控件

2、AppBarLayout

AppBarLayout 是继承LinerLayout实现的一个ViewGroup容器组件,它是为了Material Design设计的AppBar,支持手势滑动操作。默认的AppBarLayout是垂直方向的,它的作用是把AppBarLayout包裹的内容都作为AppBar。

它可以让你定制,当指定的View滚动时,AppBarLayout内部的子View实现何种动作。你想到了CoordinatorLayout,没错,并且AppBarLayout定义好了Behavior,只需要加上下面这句代码就可以使用。

app:layout_behavior="@string/appbar_scrolling_view_behavior"

AppBarLayout,相当于CoordinatorLayout的dependency View。上行代码需要加到CoordinatorLayout的child view中(下面会介绍)。

AppBarLayout子View的动作

内部的子View通过在布局中加app:layout_scrollFlags设置执行的动作,那么app:layout_scrollFlags可以设置哪些动作呢?分别如下:

1、 scroll: 跟随滚动事件一起发生移动。

就是当指定的ScrollView发生滚动时,该View也跟随一起滚动,就好像这个View也是属于这个ScrollView一样。想滚动就必须设置这个。可配合下面几项一起使用
这里写图片描述

2、 enterAlways: 当ScrollView滑动时,先滑动AppBarLayout,再响应ScrollView的内部滑动事件

这里写图片描述

3、 enterAlwaysCollapsed:是enterAlways的附加选项,一般跟enterAlways一起使用。往下滑动时,当AppBarLayout的高度达到最小高度时,就暂时不去往下滚动,直到ScrollView滑动到顶部不再滑动时,AppBarLayout再继续往下滑动

这里写图片描述

4、 exitUntilCollapsed:当AppBarLayout要往上逐渐“消逝”时,会一直往上滑动,直到剩下的的高度达到它的最小高度后,再响应ScrollView的内部滑动事件。

这里写图片描述

3、NestedScrollView

图一中,滚动操作,AppBarLayout会进行收缩和扩张,这个可滚动的view,就是这个控件。

它并没有继承ScrollView,它继承的是FrameLayout,但是它实现的效果把它可以看成是ScrollView。

作为CoordinatorLayout的child view,并在xml设置AppBarLayout类已经实现的Behavior。

<android.support.v4.widget.NestedScrollView

        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        app:layout_behavior="@string/appbar_scrolling_view_behavior">

       <!--将你的内容放在这里-->

    </android.support.v4.widget.NestedScrollView>

@string/appbar_scrolling_view_behavio 是AppBarLayout中的Behavior类名

你可能会想到,既然Behavior已经在AppBarLayout类中实现了,干嘛还非要使用NestedScrollView,使用ScrollView不可以吗?

经过我的测试,换做ScrollView还真的不行,但是看到这篇文章中,用在了SwipeRefreshLayout、ViewPager、RecycleView上,我猜想,难道只能用在android.support.v4.widget包里的控件上???

讲到这里你可能已经大概有个了解,但是好像还是有点不明白,AppBarLayout中的图片,滑动效果怎么实现,返回箭头怎么固定住的呢,title颜色渐变怎么控制?那就让我们来看看下面这个控件,一切都会明白

4、CollapsingToolbarLayout

CollapsingToolbarLayout作用是提供了一个可以折叠的Toolbar,它继承FrameLayout,它可以控制包含在CollapsingToolbarLayout中的控件(如:ImageView、Toolbar)在响应layout_behavior事件时作出相应的scrollFlags滚动事件(移除屏幕或固定在屏幕顶端)。

它通常作为AppBarLayout子View使用,所以可以给它设置layout_scrollFlags。

在CollapsingToolbarLayout的子View中可以设置以下属性:

  • layout_collapseMode (折叠模式) - 有两个值:

    • pin - 设置为这个模式时,当CollapsingToolbarLayout完全收缩后,Toolbar还可以保留在屏幕上。
    • parallax - 设置为这个模式时,在内容滚动时,CollapsingToolbarLayout中的View(比如ImageView)也可以同时滚动,实现视差滚动效果,和layout_collapseParallaxMultiplier搭配使用。
    • layout_collapseParallaxMultiplier(视差因子) - 设置视差滚动因子,值为:0~1。
  • contentScrim - 设置当CollapsingToolbarLayout完全折叠(收缩)后的背景颜色

  • expandedTitleMarginStart - 设置扩张时候(还没有收缩时)title向左填充的距离。

改变title的字体颜色:

扩张时候的title颜色:

mCollapsingToolbarLayout.setExpandedTitleColor();

收缩后在Toolbar上显示时的title的颜色:

mCollapsingToolbarLayout.setCollapsedTitleTextColor();

更多详细用法:AndroidASD完全解析06之CollapsingToolbarLayout

5、Toolbar

Android 3.0 Android 推了 ActionBar 这个控件,而到了2013 年 Google 开始大力地推动所谓的 android style,想要逐渐改善过去 android 纷乱的界面设计,希望让终端使用者尽可能在 android 手机有个一致的操作体验。官方在某些程度上认为 ActionBar 限制了 android app 的开发与设计的弹性,在Lollipop推出了ToolBar来取代过去 actionbar 的控件,而现在于 material design 中也对之有一个统一名称:app bar,在未来的 android app 中,就以 toolbar 这个元件来实现。

由于ToolBar是API 21才有的UI控件,为了适配低版本的系统,在AppCompat V7当中也提供了ToolBar,所以我们一般在开发的时候使用的是V7中的ToolBar

介绍一下使用Toolbar的步骤:

1、style

你对ActionBar的使用比较熟悉,你会发现Toolbar使用起来非常简单。ok,既然是替换,当然用Toolbar的时候就得先去把ActionBar给隐藏掉啦~

<!-- Base application theme. -->
 <style name="AppTheme.Base" parent="Theme.AppCompat">
   <!-- Customize your theme here. -->
   <item name="windowActionBar">false</item>
   <item name="android:windowNoTitle">true</item>
 </style>

 <style name="AppTheme" parent="AppTheme.Base">
</style>

2、xml文件

在 activity_main.xml 里面添加 Toolbar 控件:

<android.support.v7.widget.Toolbar
  android:id="@+id/toolbar"
  android:layout_height="?attr/actionBarSize"
  android:layout_width="match_parent" >

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

请记得用 support v7 里的 toolbar,不然然只有 API Level 21 也就是 Android 5.0 以上的版本才能使用。

3 、程序 (Java)

在 java文件 中加入 Toolbar 的声明:

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

那为啥要用ToolBar替换ActionBar呢,总应该有他的理由吧:ActionBar是固定在顶部,并不能移动,我觉得这是最大的不好,而ToolBar可以随便摆放,就可以带来很多灵活性和效果啦!

因为在这个项目中使用ToolBar特性不多,这里不过多介绍,想了解更多可以参考android:ToolBar详解(手把手教程)

参考:

CoordinatorLayout的使用如此简单

玩转AppBarLayout,更酷炫的顶部栏

关于 APP Bar(ToolBar、CoordinatorLayout、AppBarLayout、CollapsingToolbarLayout)

Material Design之CollapsingToolbarLayout使用

android:ToolBar详解(手把手教程)

Material Design系列之ToolBar即将取代ActionBar

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
好的,我知道你的问题了。针对你的问题,可以通过如下代码实现AppBarLayout的滚动监听: ```java AppBarLayout appBarLayout = findViewById(R.id.appBarLayout); appBarLayout.addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { // 在这里处理滚动事件 } }); ``` 其中,`addOnOffsetChangedListener` 方法可以添加滚动监听器,该监听器中的 `onOffsetChanged` 方法中可以处理 AppBarLayout 的滚动事件。 关于CoordinatorLayoutAppBarLayoutCollapsingToolbarLayout 和 RecyclerView 的结合使用,可以参考以下代码: ```xml <androidx.coordinatorlayout.widget.CoordinatorLayout android:id="@+id/coordinatorLayout" android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.appbar.AppBarLayout android:id="@+id/appBarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" android:fitsSystemWindows="true"> <com.google.android.material.appbar.CollapsingToolbarLayout android:id="@+id/collapsingToolbarLayout" android:layout_width="match_parent" android:layout_height="wrap_content" app:contentScrim="?attr/colorPrimary" app:layout_scrollFlags="scroll|exitUntilCollapsed"> <ImageView android:id="@+id/imageView" android:layout_width="match_parent" android:layout_height="200dp" android:scaleType="centerCrop" android:src="@drawable/image" app:layout_collapseMode="parallax" /> <com.google.android.material.toolbar.Toolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_collapseMode="pin" /> </com.google.android.material.appbar.CollapsingToolbarLayout> </com.google.android.material.appbar.AppBarLayout> <androidx.recyclerview.widget.RecyclerView android:id="@+id/recyclerView" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" /> </androidx.coordinatorlayout.widget.CoordinatorLayout> ``` 其中,`CoordinatorLayout` 是一个可以协调多个子视图之间交互的布局容器。`AppBarLayout` 是一个垂直的 LinearLayout,可以包含一个或多个子视图,用于实现应用程序栏。`CollapsingToolbarLayout` 是一个具有可折叠效果的 Toolbar 布局。`RecyclerView` 是一个可以滚动的列表视图。 以上代码实现了一个具有可折叠效果的 Toolbar 和一个可以滚动的列表视图。在 `CollapsingToolbarLayout` 中的 `ImageView` 和 `Toolbar` 都有一个 `layout_collapseMode` 属性,用于指定它们的行为。`ImageView` 的 `layout_collapseMode` 属性设置为 `parallax`,表示在滚动时具有视差效果;`Toolbar` 的 `layout_collapseMode` 属性设置为 `pin`,表示在折叠时固定在顶部。 `RecyclerView` 的 `layout_behavior` 属性设置为 `appbar_scrolling_view_behavior`,表示它是一个可以与 `AppBarLayout` 协同工作的滚动视图。这样,`AppBarLayout` 就可以根据 `RecyclerView` 的滚动情况来调整自身的显示状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

薛瑄

文章不错,请博主吃包辣条

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值