滚动时 RecyclerView 项目大小发生变化

RecyclerView Item Size changing while scrolling

第一次recyclerView加载时会正常显示。但滚动后,布局项目大小发生了变化。

这是我的item_layout

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:background="@drawable/item_border"
    android:layout_margin="@dimen/item_margin_2">
    <ImageView
        android:id="@+id/imageProduct"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:contentDescription="@string/app_name"
        android:scaleType="centerInside"
        android:src="@drawable/ic_launcher_foreground"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
         />

    <TextView
        android:id="@+id/textProductTitle"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="@android:color/black"
        android:textSize="@dimen/title_textSize"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/imageProduct"
        tools:text="TubeLight" />

    <TextView
        android:id="@+id/textProductDetailSort"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="4dp"
        android:textColor="@android:color/black"
        android:textSize="@dimen/detail_textSize"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textProductTitle"
        tools:text="warranty: 100 days" />


    <LinearLayout
        android:id="@+id/linerCartItem"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/textProductDetailSort">

        <ImageButton
            android:id="@+id/buttonRemove"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/item_border_small"
            android:src="@drawable/ic_outline_remove_24"/>

        <TextView
            android:id="@+id/textNumberItem"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@color/colorPrimaryLight"
            android:textSize="@dimen/detail_small_textSize"
            android:padding="@dimen/item_padding"
            android:textColor="@color/black"
            android:layout_margin="@dimen/item_margin_3"
            android:text="0"/>

        <ImageButton
            android:id="@+id/buttonAdd"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:background="@drawable/item_border_small"
            android:src="@drawable/ic_baseline_add_24"/>

    </LinearLayout>


    <TextView
        android:id="@+id/textViewProductPrice"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/linerCartItem"
        app:layout_constraintBottom_toBottomOf="parent"
        android:layout_marginStart="@dimen/item_margin"
        android:text="@string/title_price"/>


</androidx.constraintlayout.widget.ConstraintLayout>

这是adapter class

class ProductListAdapter(context: Context, private val cellClickListener: HomeFragment) : RecyclerView.Adapter<RecyclerView.ViewHolder>() {

    interface CellClickListener {
        fun onCellClickListener(productModel: ProductModel)
        fun onNextClicked()
        fun onPrevClicked()
        fun onAddClicked(productId: String): Int
        fun onRemoveClicked(productId: String): Int
    }

    val FOOTER_TYPE : Int = 1
    val HEADER_TYPE : Int = 2
    var context : Context = context

    private var listOfProducts = listOf<ProductModel>()


    override fun getItemViewType(position: Int): Int {

         if (position ==  listOfProducts.size) {

             return FOOTER_TYPE
         }
//         else if(position == 0){
//            return HEADER_TYPE
//         }
        return 0

    }
    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {

        if (viewType == FOOTER_TYPE){
            return ProductListViewHolderFooter(
                LayoutInflater.from(parent.context).inflate(
                    R.layout.item_product_footer,
                    parent, false
                )
            )
        }else if(viewType == HEADER_TYPE){
            return ProductListViewHolderHeader(
                LayoutInflater.from(parent.context).inflate(
                    R.layout.item_product_header,
                    parent, false
                )
            )
        }
        else{
            return ProductListViewHolder(
                context,
                LayoutInflater.from(parent.context).inflate(
                    R.layout.item_product,
                    parent,
                    false
                )
            )
        }

    }

    override fun getItemCount(): Int = listOfProducts.size + 1

    override fun onBindViewHolder(viewHolder: RecyclerView.ViewHolder, position: Int) {
        try {
            if (viewHolder is ProductListViewHolder) {
                val vh: ProductListViewHolder = viewHolder as ProductListViewHolder
                vh.bindView(listOfProducts[position], cellClickListener)

            } else if (viewHolder is ProductListViewHolderFooter) {
                val vh: ProductListViewHolderFooter = viewHolder as ProductListViewHolderFooter
                vh.bindViewFooter(listOfProducts[position], cellClickListener)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }


    }

    fun setProductList(listOfProducts: List<ProductModel>) {

        this.listOfProducts = listOfProducts
        notifyDataSetChanged()
    }
}

这是holder

class ProductListViewHolder(context: Context,itemView: View) : RecyclerView.ViewHolder(itemView){

   
    var sharedPreferences: SharedPreferences = context.getSharedPreferences(utils.PREFERENCE_FILE_NAME,
        Context.MODE_PRIVATE)
  

    fun bindView(productModel: ProductModel, cellClickListener: HomeFragment) {
        itemView.textProductTitle.text = productModel.productTitle
        itemView.textProductDetailSort.text = productModel.productDetailSort


        itemView.textViewProductPrice.text = context.getString(R.string.title_price) + ": " + productModel.price

       
        itemView.textNumberItem.text = cart

        Glide.with(itemView.context).load(productModel.productImageUrl!!).into(itemView.imageProduct)

         itemView.imageProduct.setOnClickListener{
             cellClickListener.onCellClickListener(productModel)
         }

         itemView.buttonRemove.setOnClickListener {
             val cart = cellClickListener.onRemoveClicked(productModel.productId)
             itemView.textNumberItem.text = cart.toString()
         }

         itemView.buttonAdd.setOnClickListener {
             val cart = cellClickListener.onAddClicked(productModel.productId)
             itemView.textNumberItem.text = cart.toString()
         }

    }


}

尝试调用 glide clear Glide.with(itemView.context).clear(itemView.imageProduct) 在顶部 Glide.with(itemView.context).load(productModel.productImageUrl!!).into(itemView.imageProduct)

由于无法控制 ImageView 的高度而导致 view-recycling 进程中大小不同的问题。要解决此问题,您需要对 imageProduct 属性进行一些更改。

首先,当您将 imageProduct 的开始和结束绑定到父级的开始和结束时,您应该将视图宽度设置为 0dp 以确保它填满整个 space.

其次,将 adjustViewBounds 属性设置为 true。它导致调整 ImageView 边界以保持其可绘制对象的纵横比。

第三,将layout_constrainedHeight属性设置为true。它确保视图的高度保持受限,并让视图高度保持为 wrap_content.

<ImageView
    android:id="@+id/imageProduct"
    android:layout_width="0dp"                      // 1
    android:layout_height="wrap_content"
    android:contentDescription="@string/app_name"
    android:scaleType="centerInside"
    android:src="@drawable/ic_launcher_foreground"
    android:adjustViewBounds="true"                 // 2
    app:layout_constrainedHeight="true"             // 3
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />

此外,如果您希望始终以特定的纵横比显示图像,您可以通过将高度更改为 0dp 并使用 layout_constraintDimensionRatio 定义纵横比来实现。属性,如下所示:

<ImageView
    android:id="@+id/imageProduct"
    android:layout_width="0dp"                     
    android:layout_height="0dp"                     // setting the height constrainted
    android:contentDescription="@string/app_name"
    android:scaleType="centerInside"
    android:src="@drawable/ic_launcher_foreground"
    android:adjustViewBounds="true"      
    app:layout_constraintDimensionRatio="1:1"       // to show as a square  
    app:layout_constrainedHeight="true"             
    app:layout_constraintTop_toTopOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent" />