Improve CoverImageView

This commit is contained in:
Koitharu
2021-10-08 18:56:35 +03:00
parent 1b6837d406
commit a4e1381238
3 changed files with 66 additions and 20 deletions

View File

@@ -6,10 +6,11 @@ import android.widget.LinearLayout
import androidx.appcompat.widget.AppCompatImageView import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.withStyledAttributes import androidx.core.content.withStyledAttributes
import org.koitharu.kotatsu.R import org.koitharu.kotatsu.R
import org.koitharu.kotatsu.utils.ext.resolveAdjustedSize
class CoverImageView @JvmOverloads constructor( class CoverImageView @JvmOverloads constructor(
context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0,
) : AppCompatImageView(context, attrs, defStyleAttr) { ) : AppCompatImageView(context, attrs, defStyleAttr) {
private var orientation: Int = HORIZONTAL private var orientation: Int = HORIZONTAL
@@ -21,25 +22,42 @@ class CoverImageView @JvmOverloads constructor(
} }
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
val w: Int
val h: Int
if (orientation == VERTICAL) { if (orientation == VERTICAL) {
val originalHeight = MeasureSpec.getSize(heightMeasureSpec) val desiredHeight = (drawable?.intrinsicHeight?.coerceAtLeast(0) ?: 0) +
super.onMeasure( paddingTop + paddingBottom
MeasureSpec.makeMeasureSpec( h = resolveAdjustedSize(
(originalHeight * ASPECT_RATIO_WIDTH / ASPECT_RATIO_HEIGHT).toInt(), desiredHeight.coerceAtLeast(suggestedMinimumHeight),
MeasureSpec.EXACTLY maxHeight,
), heightMeasureSpec
MeasureSpec.makeMeasureSpec(originalHeight, MeasureSpec.EXACTLY) )
val desiredWidth =
(h * ASPECT_RATIO_WIDTH / ASPECT_RATIO_HEIGHT).toInt() + paddingLeft + paddingRight
w = resolveAdjustedSize(
desiredWidth.coerceAtLeast(suggestedMinimumWidth),
maxWidth,
widthMeasureSpec
) )
} else { } else {
val originalWidth = MeasureSpec.getSize(widthMeasureSpec) val desiredWidth = (drawable?.intrinsicWidth?.coerceAtLeast(0) ?: 0) +
super.onMeasure( paddingLeft + paddingRight
MeasureSpec.makeMeasureSpec(originalWidth, MeasureSpec.EXACTLY), w = resolveAdjustedSize(
MeasureSpec.makeMeasureSpec( desiredWidth.coerceAtLeast(suggestedMinimumWidth),
(originalWidth * ASPECT_RATIO_HEIGHT / ASPECT_RATIO_WIDTH).toInt(), maxWidth,
MeasureSpec.EXACTLY widthMeasureSpec
) )
val desiredHeight =
(w * ASPECT_RATIO_HEIGHT / ASPECT_RATIO_WIDTH).toInt() + paddingTop + paddingBottom
h = resolveAdjustedSize(
desiredHeight.coerceAtLeast(suggestedMinimumHeight),
maxHeight,
heightMeasureSpec
) )
} }
val widthSize = resolveSizeAndState(w, widthMeasureSpec, 0)
val heightSize = resolveSizeAndState(h, heightMeasureSpec, 0)
setMeasuredDimension(widthSize, heightSize)
} }
companion object { companion object {

View File

@@ -5,6 +5,7 @@ import android.graphics.Rect
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu import android.view.Menu
import android.view.View import android.view.View
import android.view.View.MeasureSpec
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
@@ -53,7 +54,7 @@ var RecyclerView.firstItem: Int
inline fun View.showPopupMenu( inline fun View.showPopupMenu(
@MenuRes menuRes: Int, @MenuRes menuRes: Int,
onPrepare: (Menu) -> Unit = {}, onPrepare: (Menu) -> Unit = {},
onItemClick: PopupMenu.OnMenuItemClickListener onItemClick: PopupMenu.OnMenuItemClickListener,
) { ) {
val menu = PopupMenu(context, this) val menu = PopupMenu(context, this)
menu.inflate(menuRes) menu.inflate(menuRes)
@@ -171,4 +172,30 @@ fun BaseProgressIndicator<*>.setIndeterminateCompat(indeterminate: Boolean) {
isIndeterminate = indeterminate isIndeterminate = indeterminate
} }
} }
}
fun resolveAdjustedSize(
desiredSize: Int,
maxSize: Int,
measureSpec: Int,
): Int {
val specMode = MeasureSpec.getMode(measureSpec)
val specSize = MeasureSpec.getSize(measureSpec)
return when (specMode) {
MeasureSpec.UNSPECIFIED ->
// Parent says we can be as big as we want. Just don't be larger
// than max size imposed on ourselves.
desiredSize.coerceAtMost(maxSize)
MeasureSpec.AT_MOST ->
// Parent says we can be as big as we want, up to specSize.
// Don't be larger than specSize, and don't be larger than
// the max size imposed on ourselves.
desiredSize.coerceAtMost(specSize).coerceAtMost(maxSize)
MeasureSpec.EXACTLY ->
// No choice. Do what we are told.
specSize
else ->
// This should not happen
desiredSize
}
} }

View File

@@ -12,9 +12,9 @@
android:id="@+id/card" android:id="@+id/card"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginHorizontal="8dp"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:layout_marginBottom="4dp" android:layout_marginBottom="4dp"
android:layout_marginHorizontal="8dp"
app:cardCornerRadius="4dp" app:cardCornerRadius="4dp"
app:cardElevation="4dp"> app:cardElevation="4dp">
@@ -22,9 +22,10 @@
android:id="@+id/imageView_cover" android:id="@+id/imageView_cover"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:scaleType="centerCrop"
android:orientation="horizontal" android:orientation="horizontal"
tools:ignore="ContentDescription" /> android:scaleType="centerCrop"
tools:ignore="ContentDescription"
tools:src="@tools:sample/backgrounds/scenic[3]" />
</com.google.android.material.card.MaterialCardView> </com.google.android.material.card.MaterialCardView>
@@ -33,12 +34,12 @@
style="@style/TextAppearance.AppCompat.Body2" style="@style/TextAppearance.AppCompat.Body2"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:elegantTextHeight="false"
android:ellipsize="end" android:ellipsize="end"
android:lineSpacingExtra="-2dp" android:lineSpacingExtra="-2dp"
android:maxLines="2" android:maxLines="2"
android:paddingHorizontal="8dp" android:paddingHorizontal="8dp"
android:paddingBottom="4dp" android:paddingBottom="4dp"
android:elegantTextHeight="false"
tools:text="Sample name" /> tools:text="Sample name" />
</LinearLayout> </LinearLayout>