滚动时 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" />
第一次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" />