You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用GridLayoutManager(3列)的RecyclerView中居中ImageView尺寸异常问题

解决3列GridLayoutManager中ImageView尺寸不一致问题

问题根源

GridLayoutManager默认列宽分配逻辑下,若屏幕宽度无法被列数整除,剩余像素会被分配给部分列,导致列宽存在微小差异,进而ImageView的宽高随之变化(从日志看中间列多分配了5像素宽度,高度按比例增加10像素)。ScaleType无法解决View本身尺寸不一致的问题,需从列宽统一和布局约束入手。

解决方案

1. 强制每列宽度完全一致

通过计算精确列宽,让RecyclerView的每个Item宽度统一:

首先在初始化RecyclerView时计算列宽:

private fun initRecycler(){
    val gridLayoutManager = GridLayoutManager(context,3)
    // 计算屏幕可用宽度,减去RecyclerView的左右内边距
    val screenWidth = context.resources.displayMetrics.widthPixels
    val rvPadding = binding.rvWallpapers.paddingLeft + binding.rvWallpapers.paddingRight
    val columnWidth = (screenWidth - rvPadding) / 3

    binding.rvWallpapers.layoutManager = gridLayoutManager
    mainAdapter = MainAdapter(context, this, columnWidth) // 将列宽传入Adapter
    binding.rvWallpapers.addOnScrolledToEnd {
        binding.skvLoadingEnd.isVisible = true
        initCategory()
    }
    binding.rvWallpapers.adapter = mainAdapter
}

然后在Adapter的onBindViewHolder中给Item设置固定宽度:

class MainAdapter(
    private val context: Context,
    private val listener: OnItemClickListener,
    private val columnWidth: Int
) : RecyclerView.Adapter<MainAdapter.ViewHolder>() {

    // ... 其他代码

    override fun onBindViewHolder(holder: ViewHolder, position: Int) {
        // 设置Item根布局的固定宽度
        val layoutParams = holder.itemView.layoutParams as RecyclerView.LayoutParams
        layoutParams.width = columnWidth
        holder.itemView.layoutParams = layoutParams

        // 加载图片逻辑
        Glide.with(context)
            .load(sizesModel.url)
            .centerCrop()
            .listener(object : RequestListener<Drawable?> {
                override fun onLoadFailed(
                    e: GlideException?,
                    model: Any?,
                    target: Target<Drawable?>?,
                    isFirstResource: Boolean
                ): Boolean {
                    return false
                }

                override fun onResourceReady(
                    resource: Drawable?,
                    model: Any?,
                    target: Target<Drawable?>?,
                    dataSource: DataSource?,
                    isFirstResource: Boolean
                ): Boolean {
                    Log.d("sizes", "width: "+holder.binding.ivWallpapers.width+" height: "+holder.binding.ivWallpapers.height)
                    holder.binding.skvLoading.isVisible = false
                    return false
                }
            })
            .into(holder.binding.ivWallpapers)
    }
}

2. 用ConstraintLayout固定ImageView宽高比

在Item布局文件中,通过ConstraintLayout给ImageView设置固定宽高比,确保即使列宽有微小差异,图片比例也保持一致(建议配合方案1使用):

<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <ImageView
        android:id="@+id/ivWallpapers"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        app:layout_constraintDimensionRatio="1:2" <!-- 对应日志中宽高1:2的比例 -->
        android:scaleType="centerCrop"
        android:adjustViewBounds="true"/>

</androidx.constraintlayout.widget.ConstraintLayout>

3. 检查布局中的padding/margin

确认Item布局文件中,是否存在中间列Item额外的padding或margin设置,这也会导致ImageView尺寸不一致,需保证所有Item的内外边距完全相同。

内容的提问来源于stack exchange,提问作者sheisde

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 03:40:34