fix: Stop preview card text overlapping images (#924)

In rare occasions the preview card text could overlap the image if the
image had a portrait aspect ratio.

This seems to be due to the use of the `with(...) {}` scope function and
Kotlin's interoperability with Java setters.

Replace this with code that explicitly gets and sets the layout params
to ensure they are set correctly.
This commit is contained in:
Nik Clayton 2024-09-03 22:17:52 +02:00 committed by GitHub
parent b40e2c5f98
commit 3c1818a5d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 35 additions and 42 deletions

View File

@ -23,7 +23,6 @@ import android.util.AttributeSet
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView
import android.widget.LinearLayout import android.widget.LinearLayout
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import app.pachli.R import app.pachli.R
@ -97,7 +96,6 @@ class PreviewCardView @JvmOverloads constructor(
init { init {
val inflater = context.getSystemService(LayoutInflater::class.java) val inflater = context.getSystemService(LayoutInflater::class.java)
binding = PreviewCardBinding.inflate(inflater, this) binding = PreviewCardBinding.inflate(inflater, this)
orientation = VERTICAL
bylineAvatarTarget = object : CustomTarget<Drawable>(bylineAvatarDimen, bylineAvatarDimen) { bylineAvatarTarget = object : CustomTarget<Drawable>(bylineAvatarDimen, bylineAvatarDimen) {
override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) { override fun onResourceReady(resource: Drawable, transition: Transition<in Drawable>?) {
@ -157,8 +155,6 @@ class PreviewCardView @JvmOverloads constructor(
setStartEndLayout() setStartEndLayout()
}.build() }.build()
cardImage.scaleType = ImageView.ScaleType.CENTER_CROP
val builder = Glide.with(cardImage.context) val builder = Glide.with(cardImage.context)
.load(card.image) .load(card.image)
.dontTransform() .dontTransform()
@ -172,7 +168,6 @@ class PreviewCardView @JvmOverloads constructor(
} else if (statusDisplayOptions.useBlurhash && !card.blurhash.isNullOrBlank()) { } else if (statusDisplayOptions.useBlurhash && !card.blurhash.isNullOrBlank()) {
cardImage.show() cardImage.show()
cardImage.shapeAppearanceModel = setStartEndLayout().build() cardImage.shapeAppearanceModel = setStartEndLayout().build()
cardImage.scaleType = ImageView.ScaleType.CENTER_CROP
Glide.with(cardImage.context) Glide.with(cardImage.context)
.load(decodeBlurHash(cardImage.context, card.blurhash!!)) .load(decodeBlurHash(cardImage.context, card.blurhash!!))
@ -193,57 +188,55 @@ class PreviewCardView @JvmOverloads constructor(
} }
/** Adjusts the layout parameters to place the image above the information views */ /** Adjusts the layout parameters to place the image above the information views */
// Note: Don't try and use with(x.layoutParams) { ... } here, it can fail, see
// https://issuetracker.google.com/issues/364179209
private fun setTopBottomLayout() = with(binding) { private fun setTopBottomLayout() = with(binding) {
val cardImageShape = ShapeAppearanceModel.Builder()
// Move image to top. // Move image to top.
with(cardImage.layoutParams as ConstraintLayout.LayoutParams) { val lpCardImage = cardImage.layoutParams as ConstraintLayout.LayoutParams
height = cardImage.resources.getDimensionPixelSize(DR.dimen.card_image_vertical_height) lpCardImage.height = cardImage.resources.getDimensionPixelSize(DR.dimen.card_image_vertical_height)
width = ViewGroup.LayoutParams.MATCH_PARENT lpCardImage.width = ViewGroup.LayoutParams.MATCH_PARENT
lpCardImage.bottomToBottom = ConstraintLayout.LayoutParams.UNSET
bottomToBottom = ConstraintLayout.LayoutParams.UNSET cardImage.layoutParams = lpCardImage
}
// Move cardInfo below image // Move cardInfo below image
with(cardInfo.layoutParams as ConstraintLayout.LayoutParams) { val lpCardInfo = cardInfo.layoutParams as ConstraintLayout.LayoutParams
startToStart = ConstraintLayout.LayoutParams.PARENT_ID lpCardInfo.startToStart = ConstraintLayout.LayoutParams.PARENT_ID
topToBottom = cardImage.id lpCardInfo.topToBottom = cardImage.id
lpCardInfo.startToEnd = ConstraintLayout.LayoutParams.UNSET
lpCardInfo.topToTop = ConstraintLayout.LayoutParams.UNSET
cardInfo.layoutParams = lpCardInfo
startToEnd = ConstraintLayout.LayoutParams.UNSET // Image top corners should be rounded.
topToTop = ConstraintLayout.LayoutParams.UNSET return@with ShapeAppearanceModel.Builder()
} .setTopLeftCorner(CornerFamily.ROUNDED, cardCornerRadius)
.setTopRightCorner(CornerFamily.ROUNDED, cardCornerRadius)
cardInfo.layoutParams.height = ViewGroup.LayoutParams.MATCH_PARENT
cardImageShape.setTopLeftCorner(CornerFamily.ROUNDED, cardCornerRadius)
cardImageShape.setTopRightCorner(CornerFamily.ROUNDED, cardCornerRadius)
return@with cardImageShape
} }
/** /**
* Adjusts the layout parameters to place the image at the start, the information at * Adjusts the layout parameters to place the image at the start, the information at
* the end. * the end.
*/ */
// Note: Don't try and use with(x.layoutParams) { ... } here, it can fail, see
// https://issuetracker.google.com/issues/364179209
private fun setStartEndLayout() = with(binding) { private fun setStartEndLayout() = with(binding) {
val cardImageShape = ShapeAppearanceModel.Builder()
// Move image to start with fixed width to allow space for cardInfo. // Move image to start with fixed width to allow space for cardInfo.
with(cardImage.layoutParams as ConstraintLayout.LayoutParams) { val lpCardImage = cardImage.layoutParams as ConstraintLayout.LayoutParams
height = ConstraintLayout.LayoutParams.MATCH_CONSTRAINT lpCardImage.height = ConstraintLayout.LayoutParams.MATCH_CONSTRAINT
width = cardImage.resources.getDimensionPixelSize(DR.dimen.card_image_horizontal_width) lpCardImage.width = cardImage.resources.getDimensionPixelSize(DR.dimen.card_image_horizontal_width)
bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID lpCardImage.bottomToBottom = ConstraintLayout.LayoutParams.PARENT_ID
} cardImage.layoutParams = lpCardImage
// Move cardInfo to end of image // Move cardInfo to end of image
with(cardInfo.layoutParams as ConstraintLayout.LayoutParams) { val lpCardInfo = cardInfo.layoutParams as ConstraintLayout.LayoutParams
startToEnd = binding.cardImage.id lpCardInfo.startToEnd = cardImage.id
topToTop = ConstraintLayout.LayoutParams.PARENT_ID lpCardInfo.topToTop = ConstraintLayout.LayoutParams.PARENT_ID
lpCardInfo.startToStart = ConstraintLayout.LayoutParams.UNSET
lpCardInfo.topToBottom = ConstraintLayout.LayoutParams.UNSET
cardInfo.layoutParams = lpCardInfo
startToStart = ConstraintLayout.LayoutParams.UNSET // Image left corners should be rounded.
topToBottom = ConstraintLayout.LayoutParams.UNSET return@with ShapeAppearanceModel.Builder()
} .setTopLeftCorner(CornerFamily.ROUNDED, cardCornerRadius)
.setBottomLeftCorner(CornerFamily.ROUNDED, cardCornerRadius)
cardImageShape.setTopLeftCorner(CornerFamily.ROUNDED, cardCornerRadius)
cardImageShape.setBottomLeftCorner(CornerFamily.ROUNDED, cardCornerRadius)
return@with cardImageShape
} }
} }

View File

@ -35,7 +35,7 @@
android:layout_height="300dp" android:layout_height="300dp"
android:layout_margin="1dp" android:layout_margin="1dp"
android:importantForAccessibility="no" android:importantForAccessibility="no"
android:scaleType="center" android:scaleType="centerCrop"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@tools:sample/backgrounds/scenic" /> tools:srcCompat="@tools:sample/backgrounds/scenic" />