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;
    }
}
相关推荐
一笑的小酒馆5 小时前
Android在ksp中简单使用Room
android
meimeiqian6 小时前
flutter android端抓包工具
android·flutter
Android技术之家6 小时前
谷歌决定终止开源Android以及对开发者的影响
android·开源
每次的天空8 小时前
Android Jetpack学习总结(源码级理解)
android·学习·android jetpack
木子庆五8 小时前
Android设计模式之代理模式
android·设计模式·代理模式
在雨季等你8 小时前
创业之旅 - 反思 - 整改 - 新的方向 - 诚邀
android
Long_poem8 小时前
【自学笔记】PHP语言基础知识点总览-持续更新
android·笔记·php
fatiaozhang952710 小时前
晶晨S905L3A(B)-安卓9.0-开启ADB和ROOT-支持IPTV6-支持外置游戏系统-支持多种无线芯片-支持救砖-完美通刷线刷固件包
android·游戏·adb·华为·电视盒子·机顶盒rom·魔百盒固件
行墨10 小时前
Kotlin语言的==与===比较操作
android
圣火喵喵教11 小时前
Pixel 8 pro 刷AOSP源码 Debug 详细教程(含救砖)
android