【问题标题】:Multiple viewType RecyclerView imageView size changes on scroll滚动时多个 viewType RecyclerView imageView 大小变化
【发布时间】:2021-04-11 17:51:49
【问题描述】:

我有一个recyclerview,它有多个视图类型。其中一个在布局中有imageview

<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" />

在 BindViewHolder 中,我使用 Glide 将图像加载到视图中

// I have added this
rcvImageView.apply {
     layout(0,0,0,0)
}
Glide.with(activityContext).load(previewFile).into(rcvImageView)

我已经对代码进行了编程,因此图像文件的尺寸有效,因此适合屏幕。 但是,当我滚动recyclerView 时,相同的图像会以不同的大小显示......!! 为什么会这样?

编辑: 我在使用 Glide 设置图像之前添加了 layout(0,0,0,0),但现在的问题是,创建视图的时刻图像具有 0 尺寸,而 Glide 加载图像后的那一刻具有正确的尺寸。那一刻,所有上述项目都被向上推,因为已经创建的项目改变了它的高度!

【问题讨论】:

  • 您是否以编程方式对其进行了编程以适应屏幕?还是像您在android:scaleType 中所做的那样?
  • 不,我只在 xml ImageView 属性中使用 scaleType。
  • 谢谢。。请检查答案,如果您仍然遇到一些问题,请随时告诉我们
  • 如何在 Glide 中以编程方式使用 fitXY?
  • 您可以使用centerCrop()centerInside()fitCenter() 方法:请在此处查看stackoverflow.com/questions/34022552/…

标签: android android-layout android-recyclerview imageview android-glide


【解决方案1】:

发生这种情况是因为 ViewHolders 重用了对象,并且当您滚动时,它会显示一些以前加载的图像。您可以通过使用 .diskCacheStrategy(DiskCacheStrategy.NONE) 和 Glide 来阻止这种情况,如下所示:

Glide.with(activityContext)
     .load(yourFileDataModel)
     .diskCacheStrategy(DiskCacheStrategy.NONE)
     .into(yourImageView);

或者你可以像这样使用签名:

Glide.with(activityContext)
     .load(yourFileDataModel)
     .signature(new StringSignature(String.valueOf(System.currentTimeMillis())))
     .into(yourImageView);

【讨论】:

  • 好吧,这似乎也不起作用。 ImageViews 不是 RecyclerView 中唯一的 viewTypes。我还有其他视图类型,例如视频视图、音频视图和简单的 TextView。每个都有动态尺寸
  • 您能否编辑您的问题并为我们提供更多从您的布局到适配器的代码?
【解决方案2】:

每次在适配器的onBindViewHolder方法中回收视图时,尝试将ViewHolder中的图像重置为原始大小。

这样当视图被回收时(滚动时),ImageView 可以重置为原始大小。

onBindViewHolder(...)
    holder.imageView.layout(0, 0, 0, 0);

来源:@TWiStErRob 在here 中的评论

【讨论】:

  • 似乎现在我的行​​为符合预期。我会进一步搜索它。!谢谢
  • 但是,这会在向下滚动时产生问题,因为创建视图的那一刻高度为 0,而当 Glide 加载时,图像高度 > 0,突然所有项目都被向上推
  • @james04 只是为了确保在将图像设置为 Glide 之前调用 holder.imageView.layout()
  • 是的,参数为 0,0,0,0。
  • 你可以试试这个Glide.with(activityContext).load(previewFile).override(rcvImageView.width).into(rcvImageView)
【解决方案3】:

好吧,经过大量研究后,我结束了定制解决方案,因为您无法拥有一个具有 wrap_content 到 Width AND Height 的 ImageView 并期望 recyclerview 在滚动后不会更改大小。 我所做的是必须使用 ImageViews,一个用于 Portrait,一个用于 LandScape 和 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" />

如您所见,每个维度都有最小值和最大值。但是在它们的宽度和高度之间切换 wrap_content。因此横向图像具有固定宽度,纵向图像具有固定高度。在 onbind 视图中,根据方向我隐藏正确的 imageView 并显示另一个!

 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
     }
}

【讨论】:

    猜你喜欢
    • 2021-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多