如何将 Gridlayoutmanager 用于 recyclerView 内的可扩展卡

How to use Gridlayoutmanager for expandable cards inside a recyclerView

我正在尝试使用可扩展卡片制作网格布局,但问题是当卡片展开时,它的高度会变大,行中其他卡片的高度也会变大(以匹配第一张卡片),但是当卡片向后折叠时,所有卡片的高度都没有改变,就好像它们被展开一样。任何人都知道可能是什么问题?

编辑:

recyclerview_item.xml

<?xml version="1.0" encoding="utf-8"?>

<com.google.android.material.card.MaterialCardView 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:id="@+id/cardView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    app:cardBackgroundColor="@color/misty_rose"
    android:layout_margin="8dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <!-- Media -->
        <ImageView
            android:id="@+id/imageView"
            android:layout_width="match_parent"
            android:layout_height="300dp"
            android:layout_gravity="center_horizontal"
            android:padding="8dp"
            android:contentDescription="Photo"
            android:src="@drawable/unsplash"
            app:layout_constraintEnd_toEndOf="parent"
            app:layout_constraintStart_toStartOf="parent"
            app:layout_constraintTop_toTopOf="parent"
            android:background="@color/isabelline"
            />

        <!-- Title, secondary and supporting text -->

        <androidx.constraintlayout.widget.ConstraintLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:background="@color/misty_rose"
            app:layout_constraintTop_toBottomOf="@+id/imageView"
            android:padding="8dp">

            <TextView
                android:id="@+id/textViewCode"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Code"
                android:textAppearance="?attr/textAppearanceHeadline6"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toTopOf="parent" />

            <androidx.appcompat.widget.AppCompatImageButton
                android:id="@+id/iconExpandCard"
                android:layout_height="wrap_content"
                android:layout_width="wrap_content"
                android:padding="8dp"
                android:src="@drawable/ic_baseline_expand_more_36"
                android:background="?attr/selectableItemBackgroundBorderless"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintTop_toTopOf="parent"
                />

            <TextView
                android:id="@+id/textViewDescription"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:text="Description"
                android:textAppearance="?attr/textAppearanceBody1"
                android:textColor="?android:attr/textColorSecondary"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/textViewCode" />

            <TextView
                android:id="@+id/textViewPrice"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:text="Price"
                android:textAppearance="?attr/textAppearanceBody1"
                android:textColor="?android:attr/textColorSecondary"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/textViewDescription"/>

            <TextView
                android:id="@+id/textViewComment"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="8dp"
                android:text="Comment"
                android:textAppearance="?attr/textAppearanceBody1"
                android:textColor="?android:attr/textColorSecondary"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/textViewPrice"
                android:visibility="gone"/>

            <!-- Buttons -->
            <LinearLayout
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:layout_marginTop="8dp"
                android:orientation="horizontal"
                app:layout_constraintBottom_toBottomOf="parent"
                app:layout_constraintEnd_toEndOf="parent"
                app:layout_constraintStart_toStartOf="parent"
                app:layout_constraintTop_toBottomOf="@+id/textViewComment">

                <com.google.android.material.button.MaterialButton
                    android:id="@+id/buttonMinusArticle"
                    style="?attr/borderlessButtonStyle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_marginEnd="16dp"
                    android:width="88dp"
                    android:minWidth="40dp"
                    android:backgroundTint="@color/purple_200"
                    android:text="@string/minus"
                    android:textColor="@color/white" />

                <EditText
                    android:id="@+id/editNumberOfProducts"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:layout_gravity="center"
                    android:layout_marginEnd="16dp"
                    android:inputType="numberDecimal|number"
                    android:text="@string/zero"
                    android:textAppearance="?attr/textAppearanceBody1"
                    android:textColor="?android:attr/textColorSecondary"
                    android:textSize="18sp" />

                <com.google.android.material.button.MaterialButton
                    android:id="@+id/buttonPlusArticle"
                    style="?attr/borderlessButtonStyle"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:width="88dp"
                    android:minWidth="40dp"
                    android:backgroundTint="@color/purple_200"
                    android:text="@string/plus"
                    android:textColor="@color/white" />
            </LinearLayout>

        </androidx.constraintlayout.widget.ConstraintLayout>

    </androidx.constraintlayout.widget.ConstraintLayout>

</com.google.android.material.card.MaterialCardView>

并且在ProductListAdapter.kt中(重要部分在expandButton.setOnClickListener()):

class ProductListAdapter() : ListAdapter<Product, ProductListAdapter.ProductViewHolder>(ProductsComparator()) {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ProductViewHolder {
        return ProductViewHolder.create(parent)
    }

    override fun onBindViewHolder(holder: ProductViewHolder, position: Int) {
        val current = getItem(position)
        holder.bind(current!!)
    }

    class ProductViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
        private val productItemView: TextView = itemView.findViewById(R.id.textViewCode)
        private val productDescription : TextView = itemView.findViewById(R.id.textViewDescription)
        private val productPrice : TextView = itemView.findViewById(R.id.textViewPrice)

        fun bind(product: Product) {
            productItemView.text = product.code
            //productDescription.text = product.description
            //productPrice.text = "Price " + product.client_price.toString() 
        }

        companion object {
           
            val mapOfProducts :HashMap<String,  Int> = hashMapOf<String, Int>()

            fun create(parent: ViewGroup): ProductViewHolder {

                val view: View = LayoutInflater.from(parent.context)
                    .inflate(R.layout.recyclerview_item, parent, false)

                val minusButton : Button = view.findViewById(R.id.buttonMinusArticle)
                val plusButton : Button = view.findViewById(R.id.buttonPlusArticle)
                val productItemViewCode: TextView = view.findViewById(R.id.textViewCode)
                val expandButton : androidx.appcompat.widget.AppCompatImageButton = view.findViewById(R.id.iconExpandCard)
                val commentView :  TextView = view.findViewById(R.id.textViewComment)
                val cardView : CardView = view.findViewById(R.id.cardView)

                expandButton.setOnClickListener{
                    if (commentView.visibility == View.GONE){
                        TransitionManager.beginDelayedTransition(cardView, AutoTransition())
                        commentView.visibility = View.VISIBLE
                        expandButton.setImageResource(R.drawable.ic_baseline_expand_less_36)
                    } else {
                        TransitionManager.beginDelayedTransition(cardView, AutoTransition())
                        commentView.visibility = View.GONE
                        expandButton.setImageResource(R.drawable.ic_baseline_expand_more_36)
                    }
                }

                val editNumberOfProducts: EditText = view.findViewById(R.id.editNumberOfProducts)
                editNumberOfProducts.doAfterTextChanged {
                    val code = productItemViewCode.text.toString()

                    if (it.isNullOrBlank()) {
                        modifyText("0", view)
                        mapOfProducts.remove(code)
                        return@doAfterTextChanged
                    }
                    val originalText = it.toString()
                    try {
                        val number = originalText.toInt()
                        val numberText = originalText.toInt().toString()
                        if (originalText != numberText) {
                            modifyText(numberText, view)
                        }
                        if (number > 0) {
                            mapOfProducts[code] = number
                            d("CodeOfView", "$code $number")
                        }else {
                            mapOfProducts.remove(code)
                        }
                    } catch (e: Exception) {
                        modifyText("0", view)
                        mapOfProducts.remove(code)
                    }
                }

                minusButton.setOnClickListener {
                    var number = editNumberOfProducts.text.toString().toInt()
                    if (number>0) {
                        number -= 1
                        modifyText(number.toString(), view)
                    }
                }

                plusButton.setOnClickListener {
                    //val code = productItemViewCode.text.toString()
                    var number = editNumberOfProducts.text.toString().toInt()
                    number += 1
                    modifyText(number.toString(), view)
                }

                return ProductViewHolder(view)
            }
            private fun modifyText(numberText: String, view: View) {
                val editNumberOfProducts = view.findViewById<EditText>(R.id.editNumberOfProducts)
                editNumberOfProducts.setText(numberText)
                editNumberOfProducts.setSelection(numberText.length)
            }
        }

    }

    class ProductsComparator : DiffUtil.ItemCallback<Product>() {
        override fun areItemsTheSame(oldItem: Product, newItem: Product): Boolean {
            return oldItem === newItem
        }

        override fun areContentsTheSame(oldItem: Product, newItem: Product): Boolean {
            return oldItem.code == newItem.code
        }
    }

}

Example with images of the problem

我遇到了同样的问题,在我的情况下是垂直可扩展卡,我设法通过使用

解决了它

Adapter.notifyDataSetChanged()

在正确的地方。