浏览代码

Change cover placeholder (#6756)

Ivan Iskandar 3 年之前
父节点
当前提交
869424cd16

+ 3 - 14
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceComfortableGridHolder.kt

@@ -2,14 +2,11 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import androidx.core.view.isVisible
 import coil.dispose
-import coil.imageLoader
-import coil.request.ImageRequest
-import coil.transition.CrossfadeTransition
 import eu.davidea.flexibleadapter.FlexibleAdapter
 import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.databinding.SourceComfortableGridItemBinding
-import eu.kanade.tachiyomi.widget.StateImageViewTarget
+import eu.kanade.tachiyomi.util.view.loadAutoPause
 
 /**
  * Class used to hold the displayed data of a manga in the catalogue, like the cover or the title.
@@ -49,16 +46,8 @@ class SourceComfortableGridHolder(
 
     override fun setImage(manga: Manga) {
         binding.thumbnail.dispose()
-        if (!manga.thumbnail_url.isNullOrEmpty()) {
-            val crossfadeDuration = binding.root.context.imageLoader.defaults.transitionFactory.let {
-                if (it is CrossfadeTransition.Factory) it.durationMillis else 0
-            }
-            val request = ImageRequest.Builder(binding.root.context)
-                .data(manga)
-                .setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
-                .target(StateImageViewTarget(binding.thumbnail, binding.progress, crossfadeDuration))
-                .build()
-            itemView.context.imageLoader.enqueue(request)
+        binding.thumbnail.loadAutoPause(manga) {
+            setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
         }
     }
 }

+ 3 - 14
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceCompactGridHolder.kt

@@ -2,14 +2,11 @@ package eu.kanade.tachiyomi.ui.browse.source.browse
 
 import androidx.core.view.isVisible
 import coil.dispose
-import coil.imageLoader
-import coil.request.ImageRequest
-import coil.transition.CrossfadeTransition
 import eu.davidea.flexibleadapter.FlexibleAdapter
 import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.databinding.SourceCompactGridItemBinding
-import eu.kanade.tachiyomi.widget.StateImageViewTarget
+import eu.kanade.tachiyomi.util.view.loadAutoPause
 
 /**
  * Class used to hold the displayed data of a manga in the catalogue, like the cover or the title.
@@ -49,16 +46,8 @@ class SourceCompactGridHolder(
 
     override fun setImage(manga: Manga) {
         binding.thumbnail.dispose()
-        if (!manga.thumbnail_url.isNullOrEmpty()) {
-            val crossfadeDuration = binding.root.context.imageLoader.defaults.transitionFactory.let {
-                if (it is CrossfadeTransition.Factory) it.durationMillis else 0
-            }
-            val request = ImageRequest.Builder(binding.root.context)
-                .data(manga)
-                .setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
-                .target(StateImageViewTarget(binding.thumbnail, binding.progress, crossfadeDuration))
-                .build()
-            itemView.context.imageLoader.enqueue(request)
+        binding.thumbnail.loadAutoPause(manga) {
+            setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
         }
     }
 }

+ 3 - 14
app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/globalsearch/GlobalSearchCardHolder.kt

@@ -3,14 +3,11 @@ package eu.kanade.tachiyomi.ui.browse.source.globalsearch
 import android.view.View
 import androidx.core.view.isVisible
 import coil.dispose
-import coil.imageLoader
-import coil.request.ImageRequest
-import coil.transition.CrossfadeTransition
 import eu.davidea.viewholders.FlexibleViewHolder
 import eu.kanade.tachiyomi.data.coil.MangaCoverFetcher
 import eu.kanade.tachiyomi.data.database.models.Manga
 import eu.kanade.tachiyomi.databinding.GlobalSearchControllerCardItemBinding
-import eu.kanade.tachiyomi.widget.StateImageViewTarget
+import eu.kanade.tachiyomi.util.view.loadAutoPause
 
 class GlobalSearchCardHolder(view: View, adapter: GlobalSearchCardAdapter) :
     FlexibleViewHolder(view, adapter) {
@@ -54,16 +51,8 @@ class GlobalSearchCardHolder(view: View, adapter: GlobalSearchCardAdapter) :
 
     fun setImage(manga: Manga) {
         binding.cover.dispose()
-        if (!manga.thumbnail_url.isNullOrEmpty()) {
-            val crossfadeDuration = itemView.context.imageLoader.defaults.transitionFactory.let {
-                if (it is CrossfadeTransition.Factory) it.durationMillis else 0
-            }
-            val request = ImageRequest.Builder(itemView.context)
-                .data(manga)
-                .setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
-                .target(StateImageViewTarget(binding.cover, binding.progress, crossfadeDuration))
-                .build()
-            itemView.context.imageLoader.enqueue(request)
+        binding.cover.loadAutoPause(manga) {
+            setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false)
         }
     }
 }

+ 11 - 6
app/src/main/java/eu/kanade/tachiyomi/util/view/ImageViewExtensions.kt

@@ -1,11 +1,14 @@
 package eu.kanade.tachiyomi.util.view
 
 import android.content.Context
+import android.graphics.Color
 import android.graphics.drawable.Animatable
+import android.graphics.drawable.ColorDrawable
 import android.widget.ImageView
 import androidx.annotation.AttrRes
 import androidx.annotation.DrawableRes
 import androidx.appcompat.content.res.AppCompatResources
+import androidx.core.graphics.ColorUtils
 import coil.ImageLoader
 import coil.imageLoader
 import coil.load
@@ -38,20 +41,22 @@ fun ImageView.loadAutoPause(
     loader: ImageLoader = context.imageLoader,
     builder: ImageRequest.Builder.() -> Unit = {}
 ) {
-    // Build the original request so we can add on our success listener
     load(data, loader) {
+        val placeholderColor = ColorUtils.setAlphaComponent(Color.GRAY, 0x1F) // 12% gray
+        placeholder(ColorDrawable(placeholderColor))
+
         // Build the original request so we can add on our success listener
-        val originalBuild = apply(builder).build()
+        val originalListener = apply(builder).build().listener
         listener(
             onSuccess = { request, metadata ->
                 (request.target as? ImageViewTarget)?.drawable.let {
                     if (it is Animatable && context.animatorDurationScale == 0f) it.stop()
                 }
-                originalBuild.listener?.onSuccess(request, metadata)
+                originalListener?.onSuccess(request, metadata)
             },
-            onStart = { request -> originalBuild.listener?.onStart(request) },
-            onCancel = { request -> originalBuild.listener?.onCancel(request) },
-            onError = { request, throwable -> originalBuild.listener?.onError(request, throwable) }
+            onStart = { request -> originalListener?.onStart(request) },
+            onCancel = { request -> originalListener?.onCancel(request) },
+            onError = { request, throwable -> originalListener?.onError(request, throwable) }
         )
     }
 }

+ 0 - 43
app/src/main/java/eu/kanade/tachiyomi/widget/StateImageViewTarget.kt

@@ -1,43 +0,0 @@
-package eu.kanade.tachiyomi.widget
-
-import android.graphics.drawable.Drawable
-import android.view.View
-import android.widget.ImageView
-import androidx.core.view.isVisible
-import coil.drawable.CrossfadeDrawable
-import coil.target.ImageViewTarget
-
-/**
- * A Coil target to display an image with an optional view to show while loading.
- *
- * @param target the view where the image will be loaded
- * @param progress the view to show when the image is loading.
- * @param crossfadeDuration duration in millisecond to crossfade the result drawable
- */
-class StateImageViewTarget(
-    private val target: ImageView,
-    private val progress: View,
-    private val crossfadeDuration: Int = 0
-) : ImageViewTarget(target) {
-    override fun onStart(placeholder: Drawable?) {
-        progress.isVisible = true
-    }
-
-    override fun onSuccess(result: Drawable) {
-        progress.isVisible = false
-        if (crossfadeDuration > 0) {
-            val crossfadeResult = CrossfadeDrawable(target.drawable, result, durationMillis = crossfadeDuration)
-            target.setImageDrawable(crossfadeResult)
-            crossfadeResult.start()
-        } else {
-            target.setImageDrawable(result)
-        }
-    }
-
-    override fun onError(error: Drawable?) {
-        progress.isVisible = false
-        if (error != null) {
-            target.setImageDrawable(error)
-        }
-    }
-}

+ 0 - 13
app/src/main/res/layout/source_comfortable_grid_item.xml

@@ -9,19 +9,6 @@
     android:foreground="@drawable/library_item_selector_overlay"
     android:padding="4dp">
 
-    <com.google.android.material.progressindicator.CircularProgressIndicator
-        android:id="@+id/progress"
-        style="@style/Widget.Tachiyomi.CircularProgressIndicator.Small"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:indeterminate="true"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="@+id/thumbnail"
-        app:layout_constraintEnd_toEndOf="@+id/thumbnail"
-        app:layout_constraintStart_toStartOf="@+id/thumbnail"
-        app:layout_constraintTop_toTopOf="parent"
-        tools:visibility="visible" />
-
     <com.google.android.material.imageview.ShapeableImageView
         android:id="@+id/thumbnail"
         android:layout_width="0dp"

+ 0 - 14
app/src/main/res/layout/source_compact_grid_item.xml

@@ -55,18 +55,4 @@
         app:layout_constraintStart_toStartOf="parent"
         tools:text="Sample name" />
 
-    <com.google.android.material.progressindicator.CircularProgressIndicator
-        android:id="@+id/progress"
-        style="@style/Widget.Tachiyomi.CircularProgressIndicator.Small"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:indeterminate="true"
-        android:visibility="gone"
-        app:layout_constraintBottom_toBottomOf="parent"
-        app:layout_constraintEnd_toEndOf="parent"
-        app:layout_constraintStart_toStartOf="parent"
-        app:layout_constraintTop_toTopOf="parent"
-        tools:visibility="visible" />
-
 </androidx.constraintlayout.widget.ConstraintLayout>