在android应用中,要实现一个Recycleview,使用GridLayoutManager格子排列,且排列成4列
实现水平方向间距均等(没有外边距)。
(均分为3列5列等、竖直方向、有边距等原理相同。)
先看最终效果图。
---
xml中这样配置
<androidx.recyclerview.widget.RecyclerView
android:background="#bbffbb"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:spanCount="4"
tools:listitem="@layout/layout_item"/>
为了醒目,我们让RecyclerView背景是浅绿色。
每一个item的配置如layout_item.xml所示
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 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="wrap_content"
android:background="#ffcccc"
android:layout_height="wrap_content">
<TextView
android:id="@+id/name"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:gravity="center"
android:textSize="12sp"
app:layout_constraintEnd_toEndOf="@+id/thumb"
app:layout_constraintStart_toStartOf="@+id/thumb"
app:layout_constraintTop_toBottomOf="@+id/thumb"
tools:text='NAME' />
<com.google.android.material.imageview.ShapeableImageView
android:id="@+id/thumb"
android:layout_width="65dp"
android:layout_height="65dp"
android:scaleType="fitXY"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:background="@drawable/item_bg" />
</androidx.constraintlayout.widget.ConstraintLayout>
为了醒目,我们让每一个item的背景色为浅红色。
Activity中,我们这样设置
class MyItemDecorator:RecyclerView.ItemDecoration(){
val spanCount = 4
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
val position = parent.getChildAdapterPosition(view)
val column =position% spanCount //第几列
}
}
binding.recycleHot.addItemDecoration(MyItemDecorator())
这样的显示效果,就是,最左边item的左边距离0,最右边item的右边距离不是0。
如果layout_item.xml里root布局
android:layout_width="match_parent"
显示效果为:
---
在函数
getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
)
中
view.width始终是0,不管item的root布局layout_widht是match_parent还是wrap_content。
---
终极解法 ,
文章来源地址https://www.toymoban.com/news/detail-420893.html
我们设每个item的左右边距分别是L0、R0、L1、R1、L2、R2、L3、R3。
我们要求边距相同,即
R0+L1 = R1+L2 = R2+L3 = space(间距)
每一个item占的地方是一样的,即
L0+item内宽度+R0 = item外宽度
L1+item内宽度+R1 = item外宽度
L2+item内宽度+R2 = item外宽度
L3+item内宽度+R3 = item外宽度
即
L0+R0 = L1+R1 = L2+R2 = L3+R3 = item外宽度-item内宽度 (设为p)
我们知道L0==R3==0
故可以推算出
L0 = 0
R0 = p-L0= p
L1 = space - R0 = space-p
R1 = p-L1 = p-(space-p) = p*2 -space
L2 = space -R1 = sapce - (p*2-space) = space*2 - p*2(根据对称==R1==p*2-space)
R2 = p-L2 = p-(space*2-p*2) = p*3 - space*2(根据对称==L1==space-p)
L3 = space-R2 = space-(p*3-space*2) = space*3 -p*3(根据对称==R0==p)
R3 = 0
据此,
改善代码
class MyItemDecorator : RecyclerView.ItemDecoration() {
val spanCount = 4
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
val position = parent.getChildAdapterPosition(view)
val column = position % spanCount
fun dp2px(dp: Int): Int {
val scale = view.resources.displayMetrics.density
return (dp * scale + 0.5f).toInt()
}
val itemWidth = parent.width / 4 //item外宽度
val itemWidthInside = dp2px(65) //item内宽度
val padding = itemWidth - itemWidthInside // p
val space = (parent.width - 4 * itemWidthInside) / 3 // space
if (column == 0) {
outRect.left = 0
outRect.right = padding
} else if (column == 1) {
outRect.left = space - (padding)
outRect.right = padding * 2 - space
} else if (column == 2) {
outRect.left = space * 2 - padding * 2
outRect.right = padding * 3 - space * 2
} else if (column == 3) {
outRect.left = padding
outRect.right = 0
}
}
}
layout_item.xml也要改,把root组件的layout_width固定。
android:layout_width="65dp"
这样就能实现GridLayoutManager是4列排布,各个item间距相同,最左边和最右边的item距离边框距离为0的效果。
如果RecycleView里设置了padding,比如
```
<androidx.recyclerview.widget.RecyclerView
android:background="#bbffbb"
+ android:paddingHorizontal="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layoutManager="androidx.recyclerview.widget.GridLayoutManager"
app:spanCount="4"
tools:listitem="@layout/layout_item"/>
此时,应该在Activity中,要把parent.Width改为parent.Width - parent.paddingLeft -parent.paddingRight
override fun getItemOffsets(
outRect: Rect,
view: View,
parent: RecyclerView,
state: RecyclerView.State
) {
val position = parent.getChildAdapterPosition(view)
val column = position % spanCount
fun dp2px(dp: Int): Int {
val scale = view.resources.displayMetrics.density
return (dp * scale + 0.5f).toInt()
}
val parentWidth = parent.width - parent.paddingLeft - parent.paddingRight
val itemWidth = parentWidth / 4
val itemWidthInside = dp2px(65)
val padding = itemWidth - itemWidthInside
val space = (parentWidth - 4 * itemWidthInside) / 3
when (column) {
0 -> {
outRect.left = 0
outRect.right = padding
}
1 -> {
outRect.left = space - (padding)
outRect.right = padding * 2 - space
}
2 -> {
outRect.left = space * 2 - padding * 2
outRect.right = padding * 3 - space * 2
}
3 -> {
outRect.left = padding
outRect.right = 0
}
}
}
效果为
文章来源:https://www.toymoban.com/news/detail-420893.html
到了这里,关于RecyclerView使用GridLayoutManager 设置间距一致大小的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!