Android kotlin CoordinatorLayout使用笔记(一)
Android kotlin CoordinatorLayout使用笔记(二)
Android kotlin CoordinatorLayout使用笔记(三)
前言
这篇是前面3个所讲的一个综合应用和补全
先来看下我们实现的效果

可以看到有如下效果:
- Toobar的折叠
- 头像的放大缩小及移动
- 背景图的渐变消失
直接上代码
<?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"
tools:context=".MainActivity">
<com.google.android.material.appbar.AppBarLayout
android:id="@+id/ly_app_bar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_behavior=".BgBehavior">
<com.google.android.material.appbar.CollapsingToolbarLayout
android:id="@+id/ly_top"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_scrollFlags="scroll|exitUntilCollapsed"
app:expandedTitleMarginBottom="60dp"
app:expandedTitleGravity="end"
app:expandedTitleMarginEnd="40dp"
app:title="title"
app:collapsedTitleGravity="start">
<ImageView
android:id="@+id/img_bg"
android:layout_width="match_parent"
android:layout_height="200dp"
android:scaleType="fitXY"
android:src="@drawable/bg"
app:layout_collapseMode="parallax"
app:layout_collapseParallaxMultiplier="0.9"/>
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="46dp"
app:titleMarginStart="40dp"
app:layout_collapseMode="pin">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="返回"
android:textSize="13sp"
android:textColor="@android:color/white" />
<TextView
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="right"
android:layout_centerHorizontal="true"
android:layout_marginRight="6dp"
android:gravity="center"
android:padding="4dp"
android:textColor="#fff"
android:textSize="14sp"
android:text="菜单"/>
</androidx.appcompat.widget.Toolbar>
</com.google.android.material.appbar.CollapsingToolbarLayout>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:behavior_overlapTop="30dp"
android:overScrollMode="never"
android:scrollbars="none"
app:layout_behavior="@string/appbar_scrolling_view_behavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginBottom="40dp"
app:cardBackgroundColor="@android:color/white"
app:cardElevation="3dp" />
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginBottom="40dp"
app:cardElevation="3dp"
app:cardBackgroundColor="@android:color/white"/>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginBottom="40dp"
app:cardElevation="3dp"
app:cardBackgroundColor="@android:color/white"/>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginBottom="40dp"
app:cardElevation="3dp"
app:cardBackgroundColor="@android:color/white"/>
<androidx.cardview.widget.CardView
android:layout_width="match_parent"
android:layout_height="100dp"
android:layout_marginLeft="40dp"
android:layout_marginRight="40dp"
android:layout_marginBottom="40dp"
app:cardElevation="3dp"
app:cardBackgroundColor="@android:color/white"/>
</LinearLayout>
</androidx.core.widget.NestedScrollView>
<ImageView
android:id="@+id/img_head"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/ic_launcher"
app:layout_behavior=".HeadImageBehavior"
android:layout_gravity="center_horizontal"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
BgBehavior 背景图的出现消失behavior
class BgBehavior @JvmOverloads constructor(context: Context,
attrs: AttributeSet) : AppBarLayout.Behavior(context, attrs){
override fun onLayoutChild(parent: CoordinatorLayout, abl: AppBarLayout, layoutDirection: Int): Boolean {
val imgBg = abl.findViewById<ImageView>(R.id.img_bg)
/**
* 处于中心时候原始X轴
*/
var mOriginalHeaderX = 0
/**
* 处于中心时候原始Y轴
*/
var mOriginalHeaderY = 0
abl.addOnOffsetChangedListener(AppBarLayout.OnOffsetChangedListener { appBarLayout, verticalOffset ->
//计算imgBg从开始移动到最后的百分比
val offset = abs(verticalOffset).toFloat()
var percent = offset / (appBarLayout.totalScrollRange.toFloat() * 0.7f)
//百分大于1,直接赋值为1
if (percent >= 1) {
percent = 1f
}
val alpha = 1 - percent
//设置透明度
imgBg.alpha = alpha
})
return super.onLayoutChild(parent, abl, layoutDirection)
}
}
代码说明
这儿使用的behavior不是CoordinatorLayout.Behavior,而是 AppBarLayout.Behavior,但在用法上是没什么差别的,这儿只要是体现另外一种写法。
可以看到这里重写了onLayoutChild方法
可以通过abl.findViewById的方法直接拿到对应的View,然后就可以对View进行协调操作了
CoordinatorLayout.Behavior也可以重写onLayoutChild方法这样玩
CollapsingToolbarLayout 属性
可以看到这儿我们又多用到了一些CollapsingToolbarLayout 属性,现在来补充说明一下
- app:title 标题
-
app:titleMarginStart CollapsingToolbarLayout 折叠后title的偏移位置(这个是ToolBar的属性)
同理有titleMarginEnd,titleMarginTop等 - app:collapsedTitleGravity CollapsingToolbarLayout 展开时title的Gravity
-
app:expandedTitleMarginBottom CollapsingToolbarLayout 展开时title的偏移位置
同理有:expandedTitleMarginTop,expandedTitleMarginStart等
NestedScrollView 的 app:behavior_overlapTop属性
NestedScrollView向上偏移了30dp就是这个属性的效果

HeadImageBehavior
头像位置变化及放大缩小的behavior
class HeadImageBehavior @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null
) : CoordinatorLayout.Behavior<ImageView>(context, attrs) {
/**
* 处于中心时候原始X轴
*/
private var mOriginalHeaderX = 0
/**
* 处于中心时候原始Y轴
*/
private var mOriginalHeaderY = 0
override fun layoutDependsOn(
parent: CoordinatorLayout,
child: ImageView,
dependency: View
): Boolean {
return dependency is AppBarLayout
}
override fun onDependentViewChanged(
parent: CoordinatorLayout,
child: ImageView,
dependency: View
): Boolean {
// 计算X轴坐标
if (mOriginalHeaderX == 0) {
this.mOriginalHeaderX = (dependency.width / 2) - (child.width / 2)
}
// 计算Y轴坐标
if (mOriginalHeaderY == 0) {
mOriginalHeaderY = dependency.height - child.height;
}
//X轴百分比
var mPercentX: Float = Math.abs(dependency.y / mOriginalHeaderX)
if (mPercentX >= 1) {
mPercentX = 1f
}
var x = mOriginalHeaderX + mOriginalHeaderX * mPercentX
if (x >= dependency.width - child.width * 2) {
x = (dependency.width - child.width * 2).toFloat()
}
//Y轴百分比
var mPercentY: Float = Math.abs(dependency.y / mOriginalHeaderY)
if (mPercentY >= 1) {
mPercentY = 1f
}
var y = mOriginalHeaderY - mOriginalHeaderY * mPercentY
// 调整位置
child.x = x
child.y = y
// 放大缩小
child.scaleX = 1 - mPercentY
child.scaleY = 1 - mPercentY
return true
}
}
网友评论