Reputation: 1920
I have a recyclerview
that has multiple viewTypes. One of them has an imageview
in the layout
<ImageView
android:id="@+id/img_rcv_msg_image"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY"
app:imgBottomRightCorner="10dp"
app:imgTopLeftCorner="10dp"
app:srcCompat="@android:drawable/ic_menu_report_image"
tools:ignore="ContentDescription" />
Inside the BindViewHolder i use Glide to load the image to the view
// I have added this
rcvImageView.apply {
layout(0,0,0,0)
}
Glide.with(activityContext).load(previewFile).into(rcvImageView)
I have programmed the code so the image file has dimensions valid so it fits the screen.
However, when I scroll the recyclerView
the same image are shown with different size...!!
Why is that happening?
EDITED: I have added layout(0,0,0,0) before setting the image with Glide, but now the problem is that the moment view is created image has 0 dimensions and the moment after Glide loads the images and has corrent dimensions. That moment all the above items are getting pushed upwards because an already created item changed its height!
Upvotes: 1
Views: 684
Reputation: 1920
Well after a lot of research i ended to make a custom solution because there is no way that you can have an ImageView with wrap_content to Width AND Height and expect from the recyclerview not to change the size after scrolling. What i did is to have to ImageViews, one for Portrait and one for LandScape and Cube
<ImageView
android:id="@+id/img_snt_msg_image_landscape"
android:layout_width="320dp"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:maxWidth="320dp"
android:maxHeight="320dp"
android:minWidth="150dp"
android:minHeight="150dp"
android:src="@drawable/error_image"
app:imgBottomRightCorner="10dp"
app:imgTopLeftCorner="10dp"
tools:ignore="ContentDescription" />
<ImageView
android:id="@+id/img_snt_msg_image_portrait"
android:layout_width="wrap_content"
android:layout_height="320dp"
android:adjustViewBounds="true"
android:scaleType="fitXY"
android:maxWidth="320dp"
android:maxHeight="320dp"
android:minWidth="150dp"
android:minHeight="150dp"
android:src="@drawable/error_image"
app:imgBottomRightCorner="10dp"
app:imgTopLeftCorner="10dp"
tools:ignore="ContentDescription" />
As you can see both have a min and max for each dimension. But the toggle wrap_content between their width and height. So Landscape images have fixed width and portrait images have fixed height. Inside the onbind viewholder according with the orientation i hide the proper imageView and show the other!
sntImageViewLand.setImageDrawable(ContextCompat.getDrawable(itemView.context, R.drawable.loading_image))
sntImageViewLand.visibility = View.VISIBLE
sntImageViewPortrait.visibility = View.GONE
when (it.orientation) {
LANDSCAPE, CUBE -> {
Glide
.with(activityContext)
.load(previewFile)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(sntImageViewLand)
sntImageViewLand.setOnClickListener {
itemCallback.onRowClicked(adapterPosition, messageItem)
}
sntImageViewLand.visibility = View.VISIBLE
sntImageViewPortrait.visibility = View.GONE
}
PORTRAIT -> {
Glide
.with(activityContext)
.load(previewFile)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(sntImageViewPortrait)
sntImageViewPortrait.setOnClickListener {
itemCallback.onRowClicked(adapterPosition, messageItem)
}
sntImageViewPortrait.visibility = View.VISIBLE
sntImageViewLand.visibility = View.GONE
}
}
Upvotes: 0
Reputation: 40830
Try to reset the image in the ViewHolder
to the original size every time the views are recycled in onBindViewHolder
method of the adapter.
So that when Views are recycled (while scrolling), the ImageView
can reset to the original size.
onBindViewHolder(...)
holder.imageView.layout(0, 0, 0, 0);
Source: comment of the @TWiStErRob in here
Upvotes: 1
Reputation: 1706
This happenes because ViewHolders reuse objects and as you scroll it will show some of the previously loaded images. You can stop this by using .diskCacheStrategy(DiskCacheStrategy.NONE)
with Glide like this:
Glide.with(activityContext)
.load(yourFileDataModel)
.diskCacheStrategy(DiskCacheStrategy.NONE)
.into(yourImageView);
Or you can use Signature like this:
Glide.with(activityContext)
.load(yourFileDataModel)
.signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
.into(yourImageView);
Upvotes: 1