From fad1449de34952e12e2c5464dccf500d49fa7fa1 Mon Sep 17 00:00:00 2001 From: Ivan Iskandar <12537387+ivaniskandar@users.noreply.github.com> Date: Sun, 13 Feb 2022 23:09:49 +0700 Subject: [PATCH] Grid items optimizations (#6641) Use ConstraintLayout for ez size ratio calculation and merge cover-only view holder with compact's --- .../browse/SourceComfortableGridHolder.kt | 18 ++- .../source/browse/SourceCompactGridHolder.kt | 18 ++- .../ui/browse/source/browse/SourceItem.kt | 42 ++----- .../library/LibraryComfortableGridHolder.kt | 12 +- .../ui/library/LibraryCompactGridHolder.kt | 35 +++--- .../ui/library/LibraryCoverOnlyGridHolder.kt | 60 --------- .../tachiyomi/ui/library/LibraryItem.kt | 48 +------- ...ient_shape.xml => card_gradient_shape.xml} | 3 +- .../layout/source_comfortable_grid_item.xml | 102 ++++++++-------- .../res/layout/source_compact_grid_item.xml | 115 ++++++++++-------- .../layout/source_cover_only_grid_item.xml | 68 ----------- 11 files changed, 164 insertions(+), 357 deletions(-) delete mode 100644 app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCoverOnlyGridHolder.kt rename app/src/main/res/drawable/{gradient_shape.xml => card_gradient_shape.xml} (78%) delete mode 100644 app/src/main/res/layout/source_cover_only_grid_item.xml diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceComfortableGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceComfortableGridHolder.kt index e7b5ee56e..ebcbc16c8 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceComfortableGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceComfortableGridHolder.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.browse.source.browse -import android.view.View import androidx.core.view.isVisible import coil.clear import coil.imageLoader @@ -16,14 +15,14 @@ import eu.kanade.tachiyomi.widget.StateImageViewTarget * Class used to hold the displayed data of a manga in the catalogue, like the cover or the title. * All the elements from the layout file "item_source_grid" are available in this class. * - * @param view the inflated view for this holder. + * @param binding the inflated view for this holder. * @param adapter the adapter handling this holder. * @constructor creates a new catalogue holder. */ -class SourceComfortableGridHolder(private val view: View, private val adapter: FlexibleAdapter<*>) : - SourceHolder(view, adapter) { - - override val binding = SourceComfortableGridItemBinding.bind(view) +class SourceComfortableGridHolder( + override val binding: SourceComfortableGridItemBinding, + adapter: FlexibleAdapter<*> +) : SourceHolder(binding.root, adapter) { /** * Method called from [CatalogueAdapter.onBindViewHolder]. It updates the data for this @@ -49,15 +48,12 @@ class SourceComfortableGridHolder(private val view: View, private val adapter: F } override fun setImage(manga: Manga) { - // For rounded corners - binding.card.clipToOutline = true - binding.thumbnail.clear() if (!manga.thumbnail_url.isNullOrEmpty()) { - val crossfadeDuration = view.context.imageLoader.defaults.transition.let { + val crossfadeDuration = binding.root.context.imageLoader.defaults.transition.let { if (it is CrossfadeTransition) it.durationMillis else 0 } - val request = ImageRequest.Builder(view.context) + val request = ImageRequest.Builder(binding.root.context) .data(manga) .setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false) .target(StateImageViewTarget(binding.thumbnail, binding.progress, crossfadeDuration)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceCompactGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceCompactGridHolder.kt index 53af51d7c..0bc97039a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceCompactGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceCompactGridHolder.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.browse.source.browse -import android.view.View import androidx.core.view.isVisible import coil.clear import coil.imageLoader @@ -16,14 +15,14 @@ import eu.kanade.tachiyomi.widget.StateImageViewTarget * Class used to hold the displayed data of a manga in the catalogue, like the cover or the title. * All the elements from the layout file "item_source_grid" are available in this class. * - * @param view the inflated view for this holder. + * @param binding the inflated view for this holder. * @param adapter the adapter handling this holder. * @constructor creates a new catalogue holder. */ -open class SourceCompactGridHolder(private val view: View, private val adapter: FlexibleAdapter<*>) : - SourceHolder(view, adapter) { - - override val binding = SourceCompactGridItemBinding.bind(view) +class SourceCompactGridHolder( + override val binding: SourceCompactGridItemBinding, + adapter: FlexibleAdapter<*> +) : SourceHolder(binding.root, adapter) { /** * Method called from [CatalogueAdapter.onBindViewHolder]. It updates the data for this @@ -49,15 +48,12 @@ open class SourceCompactGridHolder(private val view: View, private val adapter: } override fun setImage(manga: Manga) { - // For rounded corners - binding.card.clipToOutline = true - binding.thumbnail.clear() if (!manga.thumbnail_url.isNullOrEmpty()) { - val crossfadeDuration = view.context.imageLoader.defaults.transition.let { + val crossfadeDuration = binding.root.context.imageLoader.defaults.transition.let { if (it is CrossfadeTransition) it.durationMillis else 0 } - val request = ImageRequest.Builder(view.context) + val request = ImageRequest.Builder(binding.root.context) .data(manga) .setParameter(MangaCoverFetcher.USE_CUSTOM_COVER, false) .target(StateImageViewTarget(binding.thumbnail, binding.progress, crossfadeDuration)) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceItem.kt index a107cd33a..a5cb700bc 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/browse/source/browse/SourceItem.kt @@ -1,10 +1,6 @@ package eu.kanade.tachiyomi.ui.browse.source.browse -import android.view.Gravity import android.view.View -import android.view.ViewGroup.LayoutParams.MATCH_PARENT -import android.widget.FrameLayout -import androidx.constraintlayout.widget.ConstraintLayout import androidx.recyclerview.widget.RecyclerView import com.fredporciuncula.flow.preferences.Preference import eu.davidea.flexibleadapter.FlexibleAdapter @@ -15,16 +11,15 @@ import eu.kanade.tachiyomi.data.database.models.Manga import eu.kanade.tachiyomi.databinding.SourceComfortableGridItemBinding import eu.kanade.tachiyomi.databinding.SourceCompactGridItemBinding import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting -import eu.kanade.tachiyomi.widget.AutofitRecyclerView class SourceItem(val manga: Manga, private val displayMode: Preference) : AbstractFlexibleItem>() { override fun getLayoutRes(): Int { return when (displayMode.get()) { - DisplayModeSetting.LIST -> R.layout.source_list_item + DisplayModeSetting.COMPACT_GRID, DisplayModeSetting.COVER_ONLY_GRID -> R.layout.source_compact_grid_item DisplayModeSetting.COMFORTABLE_GRID -> R.layout.source_comfortable_grid_item - else -> R.layout.source_compact_grid_item + DisplayModeSetting.LIST -> R.layout.source_list_item } } @@ -33,37 +28,14 @@ class SourceItem(val manga: Manga, private val displayMode: Preference> ): SourceHolder<*> { return when (displayMode.get()) { - DisplayModeSetting.LIST -> { - SourceListHolder(view, adapter) + DisplayModeSetting.COMPACT_GRID, DisplayModeSetting.COVER_ONLY_GRID -> { + SourceCompactGridHolder(SourceCompactGridItemBinding.bind(view), adapter) } DisplayModeSetting.COMFORTABLE_GRID -> { - val binding = SourceComfortableGridItemBinding.bind(view) - val parent = adapter.recyclerView as AutofitRecyclerView - val coverHeight = parent.itemWidth / 3 * 4 - view.apply { - binding.card.layoutParams = ConstraintLayout.LayoutParams( - MATCH_PARENT, - coverHeight - ) - } - SourceComfortableGridHolder(view, adapter) + SourceComfortableGridHolder(SourceComfortableGridItemBinding.bind(view), adapter) } - else -> { - val binding = SourceCompactGridItemBinding.bind(view) - val parent = adapter.recyclerView as AutofitRecyclerView - val coverHeight = parent.itemWidth / 3 * 4 - view.apply { - binding.card.layoutParams = FrameLayout.LayoutParams( - MATCH_PARENT, - coverHeight - ) - binding.gradient.layoutParams = FrameLayout.LayoutParams( - MATCH_PARENT, - coverHeight / 2, - Gravity.BOTTOM - ) - } - SourceCompactGridHolder(view, adapter) + DisplayModeSetting.LIST -> { + SourceListHolder(view, adapter) } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComfortableGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComfortableGridHolder.kt index 6cc9a39bf..74d6201d3 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComfortableGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryComfortableGridHolder.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.library -import android.view.View import androidx.core.view.isVisible import androidx.recyclerview.widget.RecyclerView import coil.clear @@ -13,17 +12,15 @@ import eu.kanade.tachiyomi.util.view.loadAnyAutoPause * Class used to hold the displayed data of a manga in the library, like the cover or the title. * All the elements from the layout file "item_source_grid" are available in this class. * - * @param view the inflated view for this holder. + * @param binding the inflated view for this holder. * @param adapter the adapter handling this holder. * @param listener a listener to react to single tap and long tap events. * @constructor creates a new library holder. */ class LibraryComfortableGridHolder( - private val view: View, + override val binding: SourceComfortableGridItemBinding, adapter: FlexibleAdapter> -) : LibraryHolder(view, adapter) { - - override val binding = SourceComfortableGridItemBinding.bind(view) +) : LibraryHolder(binding.root, adapter) { /** * Method called from [LibraryCategoryAdapter.onBindViewHolder]. It updates the data for this @@ -57,9 +54,6 @@ class LibraryComfortableGridHolder( // set local visibility if its local manga binding.badges.localText.isVisible = item.isLocal - // For rounded corners - binding.card.clipToOutline = true - // Update the cover. binding.thumbnail.clear() binding.thumbnail.loadAnyAutoPause(item.manga) diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCompactGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCompactGridHolder.kt index e5459fbdc..c92c4a64a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCompactGridHolder.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCompactGridHolder.kt @@ -1,6 +1,5 @@ package eu.kanade.tachiyomi.ui.library -import android.view.View import androidx.core.view.isVisible import coil.clear import eu.davidea.flexibleadapter.FlexibleAdapter @@ -9,19 +8,18 @@ import eu.kanade.tachiyomi.util.view.loadAnyAutoPause /** * Class used to hold the displayed data of a manga in the library, like the cover or the title. - * All the elements from the layout file "item_source_grid" are available in this class. + * All the elements from the layout file "source_compact_grid_item" are available in this class. * - * @param view the inflated view for this holder. + * @param binding the inflated view for this holder. * @param adapter the adapter handling this holder. - * @param listener a listener to react to single tap and long tap events. + * @param coverOnly true if title should be hidden a.k.a cover only mode. * @constructor creates a new library holder. */ -open class LibraryCompactGridHolder( - private val view: View, - private val adapter: FlexibleAdapter<*> -) : LibraryHolder(view, adapter) { - - override val binding = SourceCompactGridItemBinding.bind(view) +class LibraryCompactGridHolder( + override val binding: SourceCompactGridItemBinding, + adapter: FlexibleAdapter<*>, + private val coverOnly: Boolean +) : LibraryHolder(binding.root, adapter) { /** * Method called from [LibraryCategoryAdapter.onBindViewHolder]. It updates the data for this @@ -55,11 +53,20 @@ open class LibraryCompactGridHolder( // set local visibility if its local manga binding.badges.localText.isVisible = item.isLocal - // For rounded corners - binding.card.clipToOutline = true - // Update the cover. binding.thumbnail.clear() - binding.thumbnail.loadAnyAutoPause(item.manga) + if (coverOnly) { + // Cover only mode: Hides title text unless thumbnail is unavailable + if (!item.manga.thumbnail_url.isNullOrEmpty()) { + binding.thumbnail.loadAnyAutoPause(item.manga) + binding.title.isVisible = false + } else { + binding.title.text = item.manga.title + binding.title.isVisible = true + } + binding.thumbnail.foreground = null + } else { + binding.thumbnail.loadAnyAutoPause(item.manga) + } } } diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCoverOnlyGridHolder.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCoverOnlyGridHolder.kt deleted file mode 100644 index b99e38636..000000000 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryCoverOnlyGridHolder.kt +++ /dev/null @@ -1,60 +0,0 @@ -package eu.kanade.tachiyomi.ui.library - -import android.view.View -import androidx.core.view.isVisible -import androidx.recyclerview.widget.RecyclerView -import coil.clear -import eu.davidea.flexibleadapter.FlexibleAdapter -import eu.davidea.flexibleadapter.items.IFlexible -import eu.kanade.tachiyomi.databinding.SourceCoverOnlyGridItemBinding -import eu.kanade.tachiyomi.util.view.loadAnyAutoPause - -class LibraryCoverOnlyGridHolder( - view: View, - adapter: FlexibleAdapter> -) : LibraryHolder(view, adapter) { - - override val binding = SourceCoverOnlyGridItemBinding.bind(view) - - /** - * Method called from [LibraryCategoryAdapter.onBindViewHolder]. It updates the data for this - * holder with the given manga. - * - * @param item the manga item to bind. - */ - override fun onSetValues(item: LibraryItem) { - // For rounded corners - binding.badges.leftBadges.clipToOutline = true - binding.badges.rightBadges.clipToOutline = true - - // Update the unread count and its visibility. - with(binding.badges.unreadText) { - isVisible = item.unreadCount > 0 - text = item.unreadCount.toString() - } - // Update the download count and its visibility. - with(binding.badges.downloadText) { - isVisible = item.downloadCount > 0 - text = item.downloadCount.toString() - } - // Update the source language and its visibility - with(binding.badges.languageText) { - isVisible = item.sourceLanguage.isNotEmpty() - text = item.sourceLanguage - } - // set local visibility if its local manga - binding.badges.localText.isVisible = item.isLocal - - // For rounded corners - binding.card.clipToOutline = true - - // Update the cover. - binding.thumbnail.clear() - if (!item.manga.thumbnail_url.isNullOrEmpty()) { - binding.thumbnail.loadAnyAutoPause(item.manga) - } else { - // Set manga title - binding.title.text = item.manga.title - } - } -} diff --git a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt index ba6db87b1..e2e0e50a5 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/ui/library/LibraryItem.kt @@ -1,10 +1,6 @@ package eu.kanade.tachiyomi.ui.library -import android.view.Gravity import android.view.View -import android.view.ViewGroup.LayoutParams.MATCH_PARENT -import android.widget.FrameLayout -import androidx.constraintlayout.widget.ConstraintLayout import androidx.recyclerview.widget.RecyclerView import com.fredporciuncula.flow.preferences.Preference import eu.davidea.flexibleadapter.FlexibleAdapter @@ -15,10 +11,8 @@ import eu.kanade.tachiyomi.R import eu.kanade.tachiyomi.data.database.models.LibraryManga import eu.kanade.tachiyomi.databinding.SourceComfortableGridItemBinding import eu.kanade.tachiyomi.databinding.SourceCompactGridItemBinding -import eu.kanade.tachiyomi.databinding.SourceCoverOnlyGridItemBinding import eu.kanade.tachiyomi.source.SourceManager import eu.kanade.tachiyomi.ui.library.setting.DisplayModeSetting -import eu.kanade.tachiyomi.widget.AutofitRecyclerView import uy.kohesive.injekt.Injekt import uy.kohesive.injekt.api.get @@ -47,9 +41,8 @@ class LibraryItem( override fun getLayoutRes(): Int { return when (getDisplayMode()) { - DisplayModeSetting.COMPACT_GRID -> R.layout.source_compact_grid_item + DisplayModeSetting.COMPACT_GRID, DisplayModeSetting.COVER_ONLY_GRID -> R.layout.source_compact_grid_item DisplayModeSetting.COMFORTABLE_GRID -> R.layout.source_comfortable_grid_item - DisplayModeSetting.COVER_ONLY_GRID -> R.layout.source_cover_only_grid_item DisplayModeSetting.LIST -> R.layout.source_list_item } } @@ -57,42 +50,13 @@ class LibraryItem( override fun createViewHolder(view: View, adapter: FlexibleAdapter>): LibraryHolder<*> { return when (getDisplayMode()) { DisplayModeSetting.COMPACT_GRID -> { - val binding = SourceCompactGridItemBinding.bind(view) - val parent = adapter.recyclerView as AutofitRecyclerView - val coverHeight = parent.itemWidth / 3 * 4 - view.apply { - binding.card.layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, coverHeight) - binding.gradient.layoutParams = FrameLayout.LayoutParams( - MATCH_PARENT, - coverHeight / 2, - Gravity.BOTTOM - ) - } - LibraryCompactGridHolder(view, adapter) - } - DisplayModeSetting.COMFORTABLE_GRID -> { - val binding = SourceComfortableGridItemBinding.bind(view) - val parent = adapter.recyclerView as AutofitRecyclerView - val coverHeight = parent.itemWidth / 3 * 4 - view.apply { - binding.card.layoutParams = ConstraintLayout.LayoutParams( - MATCH_PARENT, - coverHeight - ) - } - LibraryComfortableGridHolder(view, adapter) + LibraryCompactGridHolder(SourceCompactGridItemBinding.bind(view), adapter, coverOnly = false) } DisplayModeSetting.COVER_ONLY_GRID -> { - val binding = SourceCoverOnlyGridItemBinding.bind(view) - val parent = adapter.recyclerView as AutofitRecyclerView - val coverHeight = parent.itemWidth / 3 * 4 - view.apply { - binding.card.layoutParams = ConstraintLayout.LayoutParams( - MATCH_PARENT, - coverHeight - ) - } - LibraryCoverOnlyGridHolder(view, adapter) + LibraryCompactGridHolder(SourceCompactGridItemBinding.bind(view), adapter, coverOnly = true) + } + DisplayModeSetting.COMFORTABLE_GRID -> { + LibraryComfortableGridHolder(SourceComfortableGridItemBinding.bind(view), adapter) } DisplayModeSetting.LIST -> { LibraryListHolder(view, adapter) diff --git a/app/src/main/res/drawable/gradient_shape.xml b/app/src/main/res/drawable/card_gradient_shape.xml similarity index 78% rename from app/src/main/res/drawable/gradient_shape.xml rename to app/src/main/res/drawable/card_gradient_shape.xml index 1ea15750d..ec22c54ed 100644 --- a/app/src/main/res/drawable/gradient_shape.xml +++ b/app/src/main/res/drawable/card_gradient_shape.xml @@ -5,8 +5,9 @@ - + diff --git a/app/src/main/res/layout/source_comfortable_grid_item.xml b/app/src/main/res/layout/source_comfortable_grid_item.xml index 393481ed9..5adca6416 100644 --- a/app/src/main/res/layout/source_comfortable_grid_item.xml +++ b/app/src/main/res/layout/source_comfortable_grid_item.xml @@ -1,5 +1,5 @@ - - + + + + + android:layout_height="wrap_content" + android:layout_marginHorizontal="4dp" + android:layout_marginTop="4dp" + app:layout_constraintEnd_toEndOf="@+id/thumbnail" + app:layout_constraintStart_toStartOf="@+id/thumbnail" + app:layout_constraintTop_toTopOf="@+id/thumbnail" /> - + - - - - - - - - - - - - - + diff --git a/app/src/main/res/layout/source_compact_grid_item.xml b/app/src/main/res/layout/source_compact_grid_item.xml index e093f7e7f..42dbc80dd 100644 --- a/app/src/main/res/layout/source_compact_grid_item.xml +++ b/app/src/main/res/layout/source_compact_grid_item.xml @@ -1,5 +1,6 @@ - - + + + + + + + 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" /> - - - - - - - - - - - - - + diff --git a/app/src/main/res/layout/source_cover_only_grid_item.xml b/app/src/main/res/layout/source_cover_only_grid_item.xml deleted file mode 100644 index dafe66452..000000000 --- a/app/src/main/res/layout/source_cover_only_grid_item.xml +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - - - - - - - - - - -