RecyclerView系列之二 ItemDecoration

一 添加分割线

less 复制代码
recyclerView.addItemDecoration(DividerItemDecoration(this@MainActivity,LinearLayout.VERTICAL))

二 什么是ItemDecoration

它是Item的装饰,在Item的四周,我们可以给它添加上自定义的装饰,我们也可以在Item的上下左右添加装饰,而且这些装饰是允许我们自定义的。如果我们想实现其它的装饰效果,就需要自定义了。

三 自定义ItemDecoration

3.1 getItemOffsets的意义

当我们要重写ItemDecoration时,主要涉及到三个函数

typescript 复制代码
@Override
public void onDraw(Canvas c, RecyclerView parent, RecyclerView.State state) {
    super.onDraw(c, parent, state);
}

@Override
public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) {
    super.onDrawOver(c, parent, state);
}

@Override
public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
    super.getItemOffsets(outRect, view, parent, state);
}

首先我们来看看getItemOffsets: 它的主要作用就是给item的四周加上边距,实现的效果类似margin,将item的四周撑开一些距离,在撑开这些距离后,我们将可以利用上面的onDraw函数,在这个距离上进行绘图。我们来看看这个方法

kotlin 复制代码
verride fun getItemOffsets(
    outRect: Rect,
    view: View,
    parent: RecyclerView,
    state: RecyclerView.State
) {
    super.getItemOffsets(outRect, view, parent, state)
}

outRect:Rect 就是表示在item的上下左右所撑开的距离。 view:View 是指当前Item的View对象 parent:RecyclerView 是指RecyclerView本身 state:Recycler.State 通过State可以获取当前RecyclerView的状态。

下面我们专门来看看Rect outRect这个参数,outRect的top,left,right,bottom四个点,是指Item上,左,右,下撑开的距离,这个值默认是0。

3.2 getItemOffsets示例 我们自定义一条红色分割线,首先我们给整个布局加上一个红色的背景色。

ini 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#F60459"
    android:orientation="vertical">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recyclerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

然后再给每个Item添加上默认的背景色白色,这样有白色的地方就不会透出背景色的红色了,而没有白色的地方就会露出红色。

ini 复制代码
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@color/white"
    android:padding="16dp">

    <TextView
        android:id="@+id/tvItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textSize="18sp"/>

</LinearLayout>

然后就是自定义我们的CustomLinearLayoutDecoration,

kotlin 复制代码
class CustomLinearLayoutDecoration : RecyclerView.ItemDecoration() {
    override fun getItemOffsets(
        outRect: Rect,
        view: View,
        parent: RecyclerView,
        state: RecyclerView.State
    ) {
        super.getItemOffsets(outRect, view, parent, state)
        outRect.top = 1 //这里暂时先直接写死1px
    }

    override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDraw(c, parent, state)
    }

    override fun onDrawOver(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
        super.onDrawOver(c, parent, state)
    }
}

效果如图展示:

这里可以看到每个Item的上方都出现了一条红线,如果我们改为底部1px,左侧50px,右侧100px,

kotlin 复制代码
override fun getItemOffsets(
    outRect: Rect,
    view: View,
    parent: RecyclerView,
    state: RecyclerView.State
) {
    super.getItemOffsets(outRect, view, parent, state)
    //这里暂时先直接写死1px
    outRect.left=50;
    outRect.right=100;
    outRect.bottom=1;
}

3.3 onDraw的用法:

kotlin 复制代码
override fun onDraw(c: Canvas, parent: RecyclerView, state: RecyclerView.State) {
    super.onDraw(c, parent, state)
}

c:Canvas是指通过getItemOffsets撑开的空白区域所对应的画布,通过这个canvas可以在getItemOffsetes所撑出来的区域进行任意绘图。现在我们想在getItemOffsets的Item的左侧撑出来的200px的距离,然后在中间画一个圆形。

注意:getItemOffsets是针对每个Item走一次,也就是说每个Item的outRect都可以不同,但是onDraw所针对整个ItemDecoration只执行一次,并不是针对Item,所有我们需要在onDraw中绘图时,一次性将所有Item的ItemOration绘制完成。

下面我们来举例每个Item也是可以设置不同的outRect,这点特别适合对第一个item进行特殊处理的情况。

ini 复制代码
private val LEFT_OFFSETS = 200  //这里暂时先直接写死200px
private val RADIUS = 20f
var mPaint: Paint = Paint().apply {
    color = Color.GREEN
}
ini 复制代码
override fun getItemOffsets(
    outRect: Rect,
    view: View,
    parent: RecyclerView,
    state: RecyclerView.State
) {
    super.getItemOffsets(outRect, view, parent, state)
    //这里获取itemview位于整个RecyclerView列表的position
    val position = parent.getChildAdapterPosition(view)
    if (position == 0) {
        outRect.left = 400;
        outRect.bottom = 1;
    } else {
        outRect.left = LEFT_OFFSETS;
        outRect.bottom = 1;
    }
}
相关推荐
木易 士心3 小时前
MPAndroidChart 用法解析和性能优化 - Kotlin & Java 双版本
android·java·kotlin
消失的旧时光-19433 小时前
Kotlin Flow 与“天然背压”(完整示例)
android·开发语言·kotlin
ClassOps3 小时前
Kotlin invoke 函数调用重载
android·开发语言·kotlin
努力学习的小廉4 小时前
初识MYSQL —— 数据类型
android·数据库·mysql
Lei活在当下8 小时前
【业务场景架构实战】7. 多代智能手表适配:Android APP 表盘编辑页的功能驱动设计
android·设计模式·架构
手机不死我是天子11 小时前
《Android 核心组件深度系列 · 第 2 篇 Service》
android
前行的小黑炭12 小时前
Compose页面切换的几种方式:Navigation、NavigationBar+HorizontalPager,会导致LaunchedEffect执行?
android·kotlin·app
前行的小黑炭12 小时前
Android :Comnpose各种副作用的使用
android·kotlin·app
BD_Marathon1 天前
【MySQL】函数
android·数据库·mysql
西西学代码1 天前
安卓开发---耳机的按键设置的UI实例
android·ui