Android CoordinatorLayout使用示例记录

原文链接: Android CoordinatorLayout使用示例记录-Stars-One的杂货小窝

简单记录下常用CoordinatorLayout的几个效果代码示例,方便后续有需求的时候参照实现

开始之前,注意下项目material 版本,下文提到的某些属性是在后续版本才有的

implementation("com.google.android.material:material:1.9.0")

一级吸顶效果

效果:

代码:

<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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">
 <com.google.android.material.appbar.AppBarLayout
 app:elevation="0dp"
 android:background="#00000000"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="vertical">
 <TextView
 android:layout_width="match_parent"
 android:layout_height="200dp"
 android:textColor="@color/white"
 android:background="#2BDC70"
 android:gravity="center"
 android:textSize="32sp"
 android:text="滚动后会隐藏"
 app:layout_scrollFlags="scroll|snap"/>
 <TextView
 android:layout_width="match_parent"
 android:layout_height="100dp"
 android:textColor="@color/white"
 android:background="#FD2E54"
 android:gravity="center"
 android:textSize="32sp"
 android:text="固定头部"
 />
 </com.google.android.material.appbar.AppBarLayout>
 <androidx.core.widget.NestedScrollView
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 app:layout_behavior="@string/appbar_scrolling_view_behavior">
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 <TextView
 android:layout_width="match_parent"
 android:text="其他内容"
 android:gravity="center_horizontal"
 android:textColor="@color/white"
 android:textSize="38sp"
 android:layout_height="700dp"
 android:background="#4A8A9E"/>
 </LinearLayout>
 </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

滚动伸缩显示标题

效果:

代码:

<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:app="http://schemas.android.com/apk/res-auto"
 android:id="@+id/main_content"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:fitsSystemWindows="true">
 <com.google.android.material.appbar.AppBarLayout
 android:id="@+id/appbar"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:fitsSystemWindows="true"
 android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar">
 <com.google.android.material.appbar.CollapsingToolbarLayout
 android:id="@+id/toolbar_layout"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 app:collapsedTitleGravity="start"
 app:contentScrim="#ff0000"
	app:expandedTitleTextColor="#00000000"
 app:collapsedTitleTextColor="@color/white"
 app:expandedTitleGravity="left|bottom"
 app:layout_scrollFlags="scroll|exitUntilCollapsed"
 app:toolbarId="@+id/toolbar">
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="240dp"
 android:orientation="vertical"
 app:layout_collapseMode="parallax">
 <ImageView
 android:layout_width="50dp"
 android:layout_height="50dp"
 android:src="@drawable/img" />
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="当前版本: "
 android:textColor="#FFFFFF" />
 </LinearLayout>
 <androidx.appcompat.widget.Toolbar
 android:id="@+id/toolbar"
 android:layout_width="match_parent"
 android:layout_height="50dp"
 app:title="关于"
 app:titleTextColor="#00000000"
 app:layout_collapseMode="pin" />
 </com.google.android.material.appbar.CollapsingToolbarLayout>
 </com.google.android.material.appbar.AppBarLayout>
 <androidx.core.widget.NestedScrollView
 android:id="@+id/rv_demo1_content"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 app:layout_behavior="@string/appbar_scrolling_view_behavior">
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 <TextView
 android:layout_width="match_parent"
 android:layout_height="700dp"
 android:background="#D88343"
 android:gravity="center"
 android:textColor="#ffffff"
 android:text="这是一个滚动布局"
 android:textSize="20sp" />
 </LinearLayout>
 </androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

layout_behavior属性设置虽然引用的string,但实际上这个string就是一个全类名!

CollapsingToolbarLayout属性补充

属性名描述
app:contentScrimCollapsingToolbarLayout完全折叠后的背景颜色
app:titleEnabled是否显示标题
app:title标题
app:toolbarIdtoolbar 对应的view id
app:statusBarScrim折叠后状态栏的背景
app:scrimVisibleHeightTrigger设置收起多少高度时,显示ContentScrim的内容
app:scrimAnimationDuration展开状态和折叠状态之间,内容转换的动画时间
app:expandedTitleTextAppearance布局张开的时候title的样式
app:expandedTitleMarginTop布局张开的时候title的margin top
app:expandedTitleMarginStart布局张开的时候title的margin start
app:expandedTitleMarginEnd布局张开的时候title的margin end
app:expandedTitleMarginBottom布局张开的时候title的margin bottom
app:expandedTitleMargin布局张开的时候title的margin
app:expandedTitleGravity布局张开的时候title的位置
app:collapsedTitleTextAppearance布局折叠的时候title的样式
app:collapsedTitleGravity布局折叠的时候title的gravity
app:expandedTitleTextColor布局张开的时候title的颜色
app:collapsedTitleTextColor布局折叠时候title的颜色

滚动隐藏底部菜单

这里使用了自定义的behavior来实现

Behavior行为控制器:实现了用户可以在子视图上进行的一个或多个交互。这些交互可能包括拖动,滑动,甩动或任何其他手势。

Behavior中常用的重写的方法:

/**
 * 确定使用Behavior的View要依赖的View的类型
 * 只要是CoordinatorLayout内的View的状态发送了变化,该方法就会执行
 * @param parent 顶层父控件CoordinatorLayout
 * @param child 我们设置这个Behavior的View
 * @param dependency 值会不断的变化,他会轮询CoordinatorLayout下所有所属的子View
 * @return 这里判断dependency所属的View是哪一个, 返回true,onDependentViewChanged才执行,否则不执行
 */
@Override
public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency)
/**
 * 当被依赖的View状态改变时回调
 * @param parent 顶层父控件CoordinatorLayout
 * @param child 我们设置这个Behavior的View
 * @param dependency 值会不断的变化,他会轮询CoordinatorLayout下所有所属的子View
 * @return 当我们改变了child的大小或者位置的时候我们需要返回true
 */
@Override
public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency)
/**
 * 当被依赖的View移除时回调
 * @param parent 顶层父控件CoordinatorLayout
 * @param child 我们设置这个Behavior的View
 * @param dependency 值会不断的变化,他会轮询CoordinatorLayout下所有所属的子View
 */
@Override
public void onDependentViewRemoved(@NonNull CoordinatorLayout parent, @NonNull View child, @NonNull View dependency)

效果(向上滑动时底部控件渐渐隐藏,向下滑动时底部控件渐渐显示):

代码:

package zhan.scollzoomlistview.activity
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.View
import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.coordinatorlayout.widget.CoordinatorLayout.Behavior
import com.google.android.material.appbar.AppBarLayout
import kotlin.math.abs
class MyBehavior: CoordinatorLayout.Behavior<View> {
 constructor() : super()
 constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs)
 override fun layoutDependsOn(
 parent: CoordinatorLayout,
 child: View,
 dependency: View
 ): Boolean {
 //这里判断dependency所属的View是哪一个,返回true,onDependentViewChanged才执行,否则不执行
 return dependency is AppBarLayout;
 }
 override fun onDependentViewChanged(
 parent: CoordinatorLayout,
 child: View,
 dependency: View
 ): Boolean {
 /*
 *这里获取dependency的top值,也就是AppBarLayout的top,因为AppBarLayout
 *在是向上滚出界面的,我们的因为是和AppBarLayout相反,每次都取反
 */
 Log.d("ttt", "onDependentViewChanged: ${dependency.top}")
 val myY = -dependency.top
 child.translationY = myY.toFloat()
 return true
 }
}

解释下:

屏幕坐标以左上角为原点,y正方向为向下,而我们手指向上滑动,实际AppBarLayout也在向上滚动(只是屏幕不显示了)

AppBarLayout的top即是y,而初始位置top为0,而后其向上滚动,这个时候的appbarlayout实际top距离已经变为负数了

而我们要修改底部菜单的translationY,实际就是相当于原始位置的y坐标偏移

  • 如果 translationY 设置为 50,那么视图的绘制位置会相对于它的原始位置向下平移 50 像素。
  • 如果 translationY 设置为 -50,那么视图的绘制位置会向上平移 50 像素。

所以:

  • 底部菜单设置正数的translationY,实现的效果就是它向下移动到消失
  • 底部菜单设置负数的translationY,实现的效果就是它向上移动到显示
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.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">
 <com.google.android.material.appbar.AppBarLayout
 app:elevation="0dp"
 android:background="#00000000"
 android:layout_width="match_parent"
 android:layout_height="wrap_content"
 android:orientation="vertical">
 <TextView
 android:layout_width="match_parent"
 android:layout_height="200dp"
 android:textColor="@color/white"
 android:background="#2BDC70"
 android:gravity="center"
 android:textSize="32sp"
 android:text="滚动后会隐藏"
 app:layout_scrollFlags="scroll|snap"/>
 <TextView
 android:layout_width="match_parent"
 android:layout_height="100dp"
 android:textColor="@color/white"
 android:background="#FD2E54"
 android:gravity="center"
 android:textSize="32sp"
 android:text="固定头部"
 />
 </com.google.android.material.appbar.AppBarLayout>
 <androidx.core.widget.NestedScrollView
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 app:layout_behavior="@string/appbar_scrolling_view_behavior">
 <LinearLayout
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:orientation="vertical">
 <TextView
 android:layout_width="match_parent"
 android:text="其他内容"
 android:gravity="center_horizontal"
 android:textColor="@color/white"
 android:textSize="38sp"
 android:layout_height="700dp"
 android:background="#4A8A9E"/>
 </LinearLayout>
 </androidx.core.widget.NestedScrollView>
	
 <!-- 底部菜单,简单写个布局来做例子 -->
 <LinearLayout
 android:layout_gravity="bottom"
 app:layout_behavior="zhan.scollzoomlistview.activity.MyBehavior"
 android:layout_width="match_parent"
 android:layout_height="100dp"
 android:background="#5AC3E7"
 android:orientation="vertical">
 <TextView
 android:layout_width="wrap_content"
 android:layout_height="wrap_content"
 android:text="模拟底部菜单"/>
 </LinearLayout>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

底部菜单的layout_behavior一定要是全类名,否则会出现崩溃问题!

参考

作者:Stars-one原文地址:https://www.cnblogs.com/stars-one/p/18543723

%s 个评论

要回复文章请先登录注册