Android之使用CoordinatorLayout相关布局实现标题栏的滑动折叠效果

前言:本篇博文不会讲的太过深奥,通过实现一个Demo来讲解相关的知识,对于知识点背后的实现原理并没有去深究,适合初次接触CoordinatorLayout相关布局的读者。

一:为什么选择CoordinatorLayout

普通的布局,诸如LinearLayout(线性布局),它里面的子布局和子控件之间是没有关联、互不影响的,比如在布局里定义了一个ListView,当滑动ListView的时候并不会对其他控件的位置和行为造成影响,标题栏控件依旧在最顶端。这样的布局就显得很平庸,毫无特色,因此,Android系统引入了CoordinatorLayout一系列相关布局,目的就是使APP页面产生各种炫酷的效果。

二:CoordinatorLayout相关布局

光靠一个CoordinatorLayout布局是完不成各种花里胡哨的页面布局的,它需要配合其他相关布局来达到效果,这些布局有AppbarLayout、CollapsingToolbarLayout等,还有一些相关的控件比如NestedScrollView、FloatingActionButton等。

1.CoordinatorLayout

        CoordinatorLayout又叫协调者布局,它是顶级的父布局,继承自FrameLayout,其他所有的布局或控件都是定义在它内部的。定义在CoordinatorLayout布局内的子布局或控件能够相互影响。它是support.design包中的控件,所以使用的时候要导入compile ‘com.android.support:design:xxx’包(xxx代表版本号)。

2.AppBarLayout

AppBarLayout布局继承自LinearLayout,所以它的默认布局方向是垂直的。它的作用就是:当CoordinatorLayout布局内的某个可滑动子View(实现了NestedScrollView机制的View,比如RecyclerView和NestedScrollView等,ListView不行)发生滑动事件时,定义在AppBarLayout布局内的子View能够实现某种动作(比如滑动,折叠,隐藏等等)方法就是在子View的属性中添加一句:app:layout_scrollFlags="xxx"。xxx代表滑动的方式,有5个选项(用RecyclerLayout做滚动子View,标题栏ToorBar做AppBarLayout内的子View举例说明):

  (1)scroll:标题栏会跟RecyclerView一起滑动(必选,不然标题栏就不会滑动)。

  (2)enterAlways:只要手指向下划滑动RecyclerView,标题栏就会马上跟着滑动出现;只要手指向上划滑动RecyclerView,标题栏就会马上跟着滑动消失。

  (3)exitUntilCollapsed:首先给标题栏设置一个最小高度,当手指向上滑动RecyclerView时,RecyclerView先不会滑动,而是先滑动标题栏,当标题栏滑到设置的最小高度的时候才会滑动RecyclerView,当RecyclerView滑到底的时候再滑动剩余的标题栏,最后标题栏全部消失。

  (4)enterAlwaysCollapsed:需要配合enterAlways一起使用。同样给标题栏设置一个最小高度,当手指向下滑动RecyclerView时,标题栏会先滑动出现,当滑动到最小高度时才滑动RecyclerView,当RecyclerView滑到顶的时候再滑动剩下的标题栏,最后标题栏全部出现。

  (5)snap:当标题栏滑动到一定程度(没有完全出现或消失)的时候,即使停止滑动标题栏仍然会完全出现或消失。

3.CollapsingToolbarLayout

该布局继承自FrameLayout,作用是对标题栏(Toorbar)进行再次包装,可以实现折叠效果,CollapsingToolbarLayout布局内的子视图不仅仅可以是标题栏,还可以添加一张图片(ImageView控件)。注:当标题栏被CollapsingToolbarLayout布局封装过后,想要更改标题栏的title需要通过调用CollapsingToolbarLayout的setTitle()方法。同时app:layout_scrollFlags="xxx"这个属性被设置在CollapsingToolbarLayout的属性上。

4.NestedScrollView

该控件是ScrollView的升级版,它们都能实现滑动效果,区别在于NestedScrollView支持嵌套滑动(在NestedScrollView内嵌套一个RecyclerView控件)。该控件就是我们Demo中要用到的滑动子View,当NestedScrollView产生滑动效果时,AppBarLayout内的子View就会做出相应动作。注:NestedScrollView可以用RecyclerLayout代替,不能用ListView(RecyclerLayout相当于ListView的升级版)。

5.FloatingActionButton

FloatingActionButton就是一个按钮控件,其本质是一个ImageVeiw。有一点要注意,Meterial Design引入了Z轴的概念,就是所有的view都有了高度,他们一层一层贴在手机屏幕上,而FloatingActionButton的Z轴高度最高,它贴在所有view的最上面,没有view能覆盖它。

6.TabLayout

TabLayout又称表格布局,主要用于页面的顶部导航栏,此处不进行过多说明,知道它是干嘛的就行。


三:构建一个Demo

上面需要用到的知识点都简单介绍了,接下来通过一个Demo来具体实现效果

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现这个效果可以采用两种方案: 1. 使用 CoordinatorLayout 实现 CoordinatorLayout 是一个非常强大的布局容器,它可以协调多个子 View 的交互行为。在这个场景下,我们可以将标题栏作为 CoordinatorLayout 的直接子 View,将 ScrollView 作为标题栏的兄弟 View,然后使用 app:layout_behavior 属性指定标题栏的行为为 AppBarLayout.ScrollingViewBehavior,这样当 ScrollView 滑动时,标题栏就会自动滑动。 示例代码如下: ```xml <androidx.coordinatorlayout.widget.CoordinatorLayout android:layout_width="match_parent" android:layout_height="match_parent"> <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="?attr/actionBarSize"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:title="My Title" /> </com.google.android.material.appbar.AppBarLayout> <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior"> <!-- Your content here --> </ScrollView> </androidx.coordinatorlayout.widget.CoordinatorLayout> ``` 需要注意的是,这种方案需要使用 AndroidX 库中的 CoordinatorLayout 和 Material Design 组件库中的 AppBarLayout 和 MaterialToolbar。 2. 使用自定义 Behavior 实现 如果你不想使用 CoordinatorLayout,或者你需要实现一些比较特殊的效果,那么可以考虑使用自定义 Behavior 实现。具体来说,我们可以定义一个 Behavior,继承自 AppBarLayout.ScrollingViewBehavior,并重写 onNestedPreScroll 方法,在 ScrollView 滑动之前处理标题栏滑动。 示例代码如下: ```java public class MyBehavior extends AppBarLayout.ScrollingViewBehavior { public MyBehavior(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onNestedPreScroll(CoordinatorLayout coordinatorLayout, View child, View target, int dx, int dy, int[] consumed) { // 计算标题栏需要滑动的距离 int distance = Math.min(child.getHeight(), dy); // 滑动标题栏 child.setTranslationY(-distance); // 更新 consumed 数组,表示已经消耗了滑动距离 consumed[1] = distance; return true; } } ``` 然后在布局文件中将标题栏的 Behavior 设置为我们定义的 MyBehavior: ```xml <com.google.android.material.appbar.AppBarLayout android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:layout_behavior=".MyBehavior"> <com.google.android.material.appbar.MaterialToolbar android:id="@+id/toolbar" android:layout_width="match_parent" android:layout_height="?attr/actionBarSize" app:title="My Title" /> </com.google.android.material.appbar.AppBarLayout> ``` 需要注意的是,这种方案需要手动处理标题栏滑动,因此需要在 onNestedPreScroll 方法中计算标题栏需要滑动的距离,并使用 setTranslationY 方法滑动标题栏。同时,需要更新 consumed 数组,表示已经消耗了滑动距离,这样才能确保滑动事件正确地传递给 ScrollView。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值