RecyclerView 项目大小在滚动时发生变化
Posted
技术标签:
【中文标题】RecyclerView 项目大小在滚动时发生变化【英文标题】:RecyclerView Item Size changing while scrolling 【发布时间】:2021-01-03 05:02:10 【问题描述】:当第一次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_
android:layout_
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_
android:layout_
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_
android:layout_
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_
android:layout_
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_
android:layout_
android:orientation="horizontal"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/textProductDetailSort">
<ImageButton
android:id="@+id/buttonRemove"
android:layout_
android:layout_
android:background="@drawable/item_border_small"
android:src="@drawable/ic_outline_remove_24"/>
<TextView
android:id="@+id/textNumberItem"
android:layout_
android:layout_
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_
android:layout_
android:background="@drawable/item_border_small"
android:src="@drawable/ic_baseline_add_24"/>
</LinearLayout>
<TextView
android:id="@+id/textViewProductPrice"
android:layout_
android:layout_
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()
【问题讨论】:
想要的是什么?在图像视图的顶部和底部有更多间隙的左侧项目还是右侧? 【参考方案1】:由于无法控制ImageView
的高度而导致的问题,导致视图回收过程中的大小不同。要解决此问题,您需要对 imageProduct
属性进行一些更改。
首先,当您将imageProduct
的起点和终点绑定到父级的起点和终点时,您应该将视图宽度设置为0dp
以确保它填满整个空间。
其次,将adjustViewBounds
属性设置为true
。它会导致调整 ImageView
边界以保持其可绘制对象的纵横比。
第三,设置layout_constrainedHeight
属性为true
。它确保视图的高度保持受限,并让视图高度保持为wrap_content
。
<ImageView
android:id="@+id/imageProduct"
android:layout_ // 1
android:layout_
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_
android:layout_ // 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" />
【讨论】:
谢谢..你拯救了我的一天..布局管理得很好。【参考方案2】:尝试调用 glide clear Glide.with(itemView.context).clear(itemView.imageProduct)
在顶部
Glide.with(itemView.context).load(productModel.productImageUrl!!).into(itemView.imageProduct)
【讨论】:
以上是关于RecyclerView 项目大小在滚动时发生变化的主要内容,如果未能解决你的问题,请参考以下文章
RecyclerView 中心项目比其他项目大,滚动时大小不一
当 Kotlin 中的数据发生变化时,如何在 RecyclerView 中重新绑定项目?