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

Posted

技术标签:

【中文标题】如何将 Gridlayoutmanager 用于 recyclerView 内的可扩展卡片【英文标题】:How to use Gridlayoutmanager for expandable cards inside a recyclerView 【发布时间】:2021-05-17 22:07:12 【问题描述】:

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

编辑:

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_
    android:layout_
    app:cardBackgroundColor="@color/misty_rose"
    android:layout_margin="8dp">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_
        android:layout_>

        <!-- Media -->
        <ImageView
            android:id="@+id/imageView"
            android:layout_
            android:layout_
            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_
            android:layout_
            android:background="@color/misty_rose"
            app:layout_constraintTop_toBottomOf="@+id/imageView"
            android:padding="8dp">

            <TextView
                android:id="@+id/textViewCode"
                android:layout_
                android:layout_
                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_
                android:layout_
                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_
                android:layout_
                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_
                android:layout_
                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_
                android:layout_
                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_
                android:layout_
                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_
                    android:layout_
                    android:layout_marginEnd="16dp"
                    android:
                    android:minWidth="40dp"
                    android:backgroundTint="@color/purple_200"
                    android:text="@string/minus"
                    android:textColor="@color/white" />

                <EditText
                    android:id="@+id/editNumberOfProducts"
                    android:layout_
                    android:layout_
                    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_
                    android:layout_
                    android:
                    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

【问题讨论】:

嗨 Gheorghe, 仅通过阅读您的文字很难说出问题所在,如果您分享您的代码和您正在尝试的内容的快照,那就太好了。去做。 嗨@ajay,感谢您的回复,我刚刚编辑了问题 确保您使用的是 Adapter.notifyDataSetChanged()。那应该可以解决这个问题。让我知道这是否能解决您的问题。 @AjayJG 谢谢!它解决了我的问题!这是我第一次为 android 做东西,所以我最初不知道在哪里使用 notifyDataSetChanged(),所以我认为它不起作用,但经过一些更改它修复了所有问题。 【参考方案1】:

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

Adapter.notifyDataSetChanged()

在正确的地方。

【讨论】:

以上是关于如何将 Gridlayoutmanager 用于 recyclerView 内的可扩展卡片的主要内容,如果未能解决你的问题,请参考以下文章

如何将gridlayoutManager每列的宽度设置为wrapContent在android中不固定大小

如何将 GridLayoutManager 中的项目固定为具有不同跨度计数的父项的开始和结束

如何摆脱 GridLayoutManager 项目之间的差距

RecyclerView GridLayoutManager:如何自动检测跨度计数?

GridLayoutManager 如何在下一行显示不同的视图类型

使用 GridLayoutManager 实现 RecyclerView 时将项目居中