From 65077c1fba7c539252ad155a65d1151f57948d0b Mon Sep 17 00:00:00 2001 From: Koitharu Date: Wed, 13 Mar 2024 15:46:40 +0200 Subject: [PATCH] Update chapters grid ui --- .../details/ui/adapter/ChapterGridItemAD.kt | 23 ++-- .../ui/adapter/ChaptersSelectionDecoration.kt | 48 +++++++ .../pager/chapters/ChapterGridSpanHelper.kt | 46 +++++++ .../ui/pager/chapters/ChaptersFragment.kt | 16 +-- .../ui/adapter/TypedListSpacingDecoration.kt | 3 +- .../kotatsu/reader/ui/ChaptersSheet.kt | 4 +- app/src/main/res/layout/item_chapter_grid.xml | 126 ++++++++++-------- app/src/main/res/values/dimens.xml | 4 + 8 files changed, 190 insertions(+), 80 deletions(-) create mode 100644 app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChapterGridSpanHelper.kt diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterGridItemAD.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterGridItemAD.kt index d9eee1600..c5f2a8c1d 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterGridItemAD.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChapterGridItemAD.kt @@ -1,24 +1,21 @@ package org.koitharu.kotatsu.details.ui.adapter import android.graphics.Typeface -import androidx.core.content.ContextCompat import androidx.core.view.isVisible import com.hannesdorfmann.adapterdelegates4.dsl.adapterDelegateViewBinding -import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.core.model.formatNumber import org.koitharu.kotatsu.core.ui.list.AdapterDelegateClickListenerAdapter import org.koitharu.kotatsu.core.ui.list.OnListItemClickListener -import org.koitharu.kotatsu.core.util.ext.drawableStart import org.koitharu.kotatsu.core.util.ext.getThemeColorStateList import org.koitharu.kotatsu.databinding.ItemChapterGridBinding import org.koitharu.kotatsu.details.ui.model.ChapterListItem import org.koitharu.kotatsu.list.ui.model.ListModel -import kotlin.math.roundToInt fun chapterGridItemAD( clickListener: OnListItemClickListener, ) = adapterDelegateViewBinding( viewBinding = { inflater, parent -> ItemChapterGridBinding.inflate(inflater, parent, false) }, - on = { item, _, _ -> item is ChapterListItem && item.isGrid } + on = { item, _, _ -> item is ChapterListItem && item.isGrid }, ) { val eventListener = AdapterDelegateClickListenerAdapter(this, clickListener) @@ -27,33 +24,29 @@ fun chapterGridItemAD( bind { payloads -> if (payloads.isEmpty()) { - binding.textViewTitle.text = item.chapter.number.roundToInt().toString() + binding.textViewTitle.text = item.chapter.formatNumber() } + binding.imageViewNew.isVisible = item.isNew + binding.imageViewCurrent.isVisible = item.isCurrent + binding.imageViewBookmarked.isVisible = item.isBookmarked + binding.imageViewDownloaded.isVisible = item.isDownloaded + when { item.isCurrent -> { - binding.textViewTitle.drawableStart = ContextCompat.getDrawable(context, R.drawable.ic_current_chapter) binding.textViewTitle.setTextColor(context.getThemeColorStateList(android.R.attr.textColorPrimary)) binding.textViewTitle.typeface = Typeface.DEFAULT_BOLD } item.isUnread -> { - binding.textViewTitle.drawableStart = if (item.isNew) { - ContextCompat.getDrawable(context, R.drawable.ic_new) - } else { - null - } binding.textViewTitle.setTextColor(context.getThemeColorStateList(android.R.attr.textColorPrimary)) binding.textViewTitle.typeface = Typeface.DEFAULT } else -> { - binding.textViewTitle.drawableStart = null binding.textViewTitle.setTextColor(context.getThemeColorStateList(android.R.attr.textColorHint)) binding.textViewTitle.typeface = Typeface.DEFAULT } } - binding.imageViewBookmarked.isVisible = item.isBookmarked - binding.imageViewDownloaded.isVisible = item.isDownloaded } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt index 7b8b46694..cfc7a1e11 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/adapter/ChaptersSelectionDecoration.kt @@ -6,8 +6,11 @@ import android.graphics.Color import android.graphics.Paint import android.graphics.RectF import android.view.View +import androidx.cardview.widget.CardView +import androidx.core.content.ContextCompat import androidx.core.graphics.ColorUtils import androidx.recyclerview.widget.RecyclerView +import org.koitharu.kotatsu.R import org.koitharu.kotatsu.core.ui.list.decor.AbstractSelectionItemDecoration import org.koitharu.kotatsu.core.util.ext.getItem import org.koitharu.kotatsu.core.util.ext.getThemeColor @@ -18,6 +21,14 @@ class ChaptersSelectionDecoration(context: Context) : AbstractSelectionItemDecor private val paint = Paint(Paint.ANTI_ALIAS_FLAG) private val radius = context.resources.getDimension(materialR.dimen.abc_control_corner_material) + private val checkIcon = ContextCompat.getDrawable(context, materialR.drawable.ic_mtrl_checked_circle) + private val iconOffset = context.resources.getDimensionPixelOffset(R.dimen.chapter_check_offset) + private val iconSize = context.resources.getDimensionPixelOffset(R.dimen.chapter_check_size) + private val strokeColor = context.getThemeColor(materialR.attr.colorPrimary, Color.RED) + private val fillColor = ColorUtils.setAlphaComponent( + ColorUtils.blendARGB(strokeColor, context.getThemeColor(materialR.attr.colorSurface), 0.8f), + 0x74, + ) init { paint.color = ColorUtils.setAlphaComponent( @@ -25,6 +36,12 @@ class ChaptersSelectionDecoration(context: Context) : AbstractSelectionItemDecor 98, ) paint.style = Paint.Style.FILL + hasBackground = false + hasForeground = true + isIncludeDecorAndMargins = false + + paint.strokeWidth = context.resources.getDimension(R.dimen.selection_stroke_width) + checkIcon?.setTint(strokeColor) } override fun getItemId(parent: RecyclerView, child: View): Long { @@ -40,6 +57,37 @@ class ChaptersSelectionDecoration(context: Context) : AbstractSelectionItemDecor bounds: RectF, state: RecyclerView.State, ) { + if (child is CardView) { + return + } canvas.drawRoundRect(bounds, radius, radius, paint) } + + override fun onDrawForeground( + canvas: Canvas, + parent: RecyclerView, + child: View, + bounds: RectF, + state: RecyclerView.State + ) { + if (child !is CardView) { + return + } + val radius = child.radius + paint.color = fillColor + paint.style = Paint.Style.FILL + canvas.drawRoundRect(bounds, radius, radius, paint) + paint.color = strokeColor + paint.style = Paint.Style.STROKE + canvas.drawRoundRect(bounds, radius, radius, paint) + checkIcon?.run { + setBounds( + (bounds.right - iconSize - iconOffset).toInt(), + (bounds.top + iconOffset).toInt(), + (bounds.right - iconOffset).toInt(), + (bounds.top + iconOffset + iconSize).toInt(), + ) + draw(canvas) + } + } } diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChapterGridSpanHelper.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChapterGridSpanHelper.kt new file mode 100644 index 000000000..4c19a2a77 --- /dev/null +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChapterGridSpanHelper.kt @@ -0,0 +1,46 @@ +package org.koitharu.kotatsu.details.ui.pager.chapters + +import android.view.View +import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.RecyclerView +import org.koitharu.kotatsu.R +import kotlin.math.roundToInt + +class ChapterGridSpanHelper private constructor() : View.OnLayoutChangeListener { + + override fun onLayoutChange( + v: View?, + left: Int, + top: Int, + right: Int, + bottom: Int, + oldLeft: Int, + oldTop: Int, + oldRight: Int, + oldBottom: Int + ) { + val rv = v as? RecyclerView ?: return + if (rv.width > 0) { + apply(rv) + } + } + + private fun apply(rv: RecyclerView) { + (rv.layoutManager as? GridLayoutManager)?.spanCount = getSpanCount(rv) + } + + companion object { + + fun attach(view: RecyclerView) { + val helper = ChapterGridSpanHelper() + view.addOnLayoutChangeListener(helper) + helper.apply(view) + } + + fun getSpanCount(view: RecyclerView): Int { + val cellWidth = view.resources.getDimension(R.dimen.chapter_grid_width) + val estimatedCount = (view.width / cellWidth).roundToInt() + return estimatedCount.coerceAtLeast(2) + } + } +} diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersFragment.kt b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersFragment.kt index 16bfcb79a..85e4f6c31 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersFragment.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/details/ui/pager/chapters/ChaptersFragment.kt @@ -1,7 +1,6 @@ package org.koitharu.kotatsu.details.ui.pager.chapters import android.os.Bundle -import android.util.Log import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem @@ -65,19 +64,20 @@ class ChaptersFragment : registryOwner = this, callback = this, ) + viewModel.isChaptersInGridView.observe(viewLifecycleOwner) { chaptersInGridView -> + binding.recyclerViewChapters.layoutManager = if (chaptersInGridView) { + GridLayoutManager(context, ChapterGridSpanHelper.getSpanCount(binding.recyclerViewChapters)) + } else { + LinearLayoutManager(context) + } + } with(binding.recyclerViewChapters) { addItemDecoration(TypedListSpacingDecoration(context, true)) checkNotNull(selectionController).attachToRecyclerView(this) setHasFixedSize(true) isNestedScrollingEnabled = false adapter = chaptersAdapter - } - viewModel.isChaptersInGridView.observe(viewLifecycleOwner) { chaptersInGridView -> - binding.recyclerViewChapters.layoutManager = if (chaptersInGridView) { - GridLayoutManager(context, 4) - } else { - LinearLayoutManager(context) - } + ChapterGridSpanHelper.attach(this) } viewModel.isLoading.observe(viewLifecycleOwner, this::onLoadingStateChanged) viewModel.chapters diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/TypedListSpacingDecoration.kt b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/TypedListSpacingDecoration.kt index f93403d52..7984879f5 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/TypedListSpacingDecoration.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/list/ui/adapter/TypedListSpacingDecoration.kt @@ -63,10 +63,11 @@ class TypedListSpacingDecoration( ListItemType.CATEGORY_LARGE, ListItemType.NAV_ITEM, ListItemType.CHAPTER_LIST, - ListItemType.CHAPTER_GRID, null, -> outRect.set(0) + ListItemType.CHAPTER_GRID -> outRect.set(spacingSmall) + ListItemType.TIP -> outRect.set(0) // TODO } if (addHorizontalPadding && !itemType.isEdgeToEdge()) { diff --git a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ChaptersSheet.kt b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ChaptersSheet.kt index 164305bf5..a9244c12f 100644 --- a/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ChaptersSheet.kt +++ b/app/src/main/kotlin/org/koitharu/kotatsu/reader/ui/ChaptersSheet.kt @@ -21,6 +21,7 @@ import org.koitharu.kotatsu.databinding.SheetChaptersBinding import org.koitharu.kotatsu.details.ui.adapter.ChaptersAdapter import org.koitharu.kotatsu.details.ui.mapChapters import org.koitharu.kotatsu.details.ui.model.ChapterListItem +import org.koitharu.kotatsu.details.ui.pager.chapters.ChapterGridSpanHelper import org.koitharu.kotatsu.details.ui.withVolumeHeaders import org.koitharu.kotatsu.history.data.PROGRESS_NONE import org.koitharu.kotatsu.list.ui.adapter.TypedListSpacingDecoration @@ -90,8 +91,9 @@ class ChaptersSheet : BaseAdaptiveSheet(), adapter.items = chapters } } + ChapterGridSpanHelper.attach(binding.recyclerView) binding.recyclerView.layoutManager = if (settings.isChaptersGridView) { - GridLayoutManager(context, 4) + GridLayoutManager(context, ChapterGridSpanHelper.getSpanCount(binding.recyclerView)) } else { LinearLayoutManager(context) } diff --git a/app/src/main/res/layout/item_chapter_grid.xml b/app/src/main/res/layout/item_chapter_grid.xml index 670de9ff8..394aa4349 100644 --- a/app/src/main/res/layout/item_chapter_grid.xml +++ b/app/src/main/res/layout/item_chapter_grid.xml @@ -1,68 +1,84 @@ - + android:layout_height="wrap_content" + tools:layout_width="@dimen/chapter_grid_width"> - + - + - + - + - + - + - + - - - - - + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 9225b0922..fb7b652c9 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -40,6 +40,7 @@ 8dp 12dp 120dp + 80dp 8dp 124dp @@ -55,6 +56,9 @@ 24dp 8dp + 16dp + 6dp + 20dp 28dp