动态设置宽度后RecyclerView Item无法居中问题求助
RecyclerView Item设置90%宽度后居中问题解决方案
问题场景
为让RecyclerView Adapter更具动态性,通过代码将Item宽度设为父布局的90%后,无法实现Item居中;硬编码XML的margin虽能实现居中,但灵活性不足;RecyclerView不支持android:gravity属性,设置android:layout_gravity也无效果;尝试在ViewHolder.from(parent).apply中添加padding时,出现“Val cannot be reassigned”错误。Item布局使用ConstraintLayout,相关代码如下:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder.from(parent).apply { val targetWidth = parent.measuredWidth * .9 itemView.layoutParams.width = targetWidth.toInt() } }
解决方案
方法1:用ItemDecoration实现动态居中
这是最灵活的方案,无需修改Item布局,通过给RecyclerView添加装饰类,自动为每个Item分配均等的左右间距:
class CenterItemDecoration(private val horizontalMarginRatio: Float = 0.05f) : RecyclerView.ItemDecoration() { override fun getItemOffsets( outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State ) { super.getItemOffsets(outRect, view, parent, state) // 计算左右间距:父布局宽度的5%(Item占90%,剩余10%平分给左右) val horizontalMargin = (parent.width * horizontalMarginRatio).toInt() outRect.left = horizontalMargin outRect.right = horizontalMargin } }
在RecyclerView初始化时添加该装饰:
recyclerView.addItemDecoration(CenterItemDecoration())
方法2:动态设置Item的MarginLayoutParams
直接在onCreateViewHolder中修改Item的布局参数,设置左右margin实现居中:
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { return ViewHolder.from(parent).apply { val targetWidth = (parent.measuredWidth * 0.9).toInt() // 将布局参数强转为MarginLayoutParams val layoutParams = itemView.layoutParams as ViewGroup.MarginLayoutParams layoutParams.width = targetWidth // 计算左右margin:(父布局宽度 - Item宽度) / 2 val horizontalMargin = (parent.measuredWidth - targetWidth) / 2 layoutParams.leftMargin = horizontalMargin layoutParams.rightMargin = horizontalMargin // 重新设置布局参数 itemView.layoutParams = layoutParams } }
关于“Val cannot be reassigned”错误的说明
直接给itemView.paddingLeft这类属性赋值会报错,因为这些是只读的val属性。如需设置padding,需调用setPadding()方法:
val horizontalPadding = (parent.measuredWidth * 0.05).toInt() itemView.setPadding(horizontalPadding, itemView.paddingTop, horizontalPadding, itemView.paddingBottom)
不过这种方式会压缩Item内部的内容区域,优先推荐前两种设置margin的方案。
内容的提问来源于stack exchange,提问作者yazmnh87
相关产品推荐
相关产品推荐

