From 802448cb5a85fe043d77600641b55bc10d92ba77 Mon Sep 17 00:00:00 2001 From: Koitharu Date: Sun, 24 Jul 2022 15:14:03 +0300 Subject: [PATCH] Fix grid size computing --- .../ui/list/FavouritesListFragment.kt | 13 +++---- .../kotatsu/history/ui/HistoryListFragment.kt | 13 +++---- .../kotatsu/list/ui/MangaListFragment.kt | 22 +++++------- .../kotatsu/list/ui/MangaListSpanResolver.kt | 35 +++++++++---------- .../kotatsu/local/ui/LocalListFragment.kt | 17 ++++----- .../ui/thumbnails/PagesThumbnailsSheet.kt | 15 ++++---- .../remotelist/ui/RemoteListFragment.kt | 9 +++-- .../kotatsu/search/ui/SearchFragment.kt | 7 ++-- .../suggestions/ui/SuggestionsFragment.kt | 7 ++-- 9 files changed, 70 insertions(+), 68 deletions(-) diff --git a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt index edacd269f..343c873fc 100644 --- a/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/favourites/ui/list/FavouritesListFragment.kt @@ -9,6 +9,7 @@ import androidx.appcompat.widget.PopupMenu import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.core.parameter.parametersOf import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.list.ListSelectionController import org.koitharu.kotatsu.core.ui.titleRes import org.koitharu.kotatsu.favourites.ui.categories.FavouriteCategoriesActivity import org.koitharu.kotatsu.list.ui.MangaListFragment @@ -48,26 +49,26 @@ class FavouritesListFragment : MangaListFragment(), PopupMenu.OnMenuItemClickLis return true } - override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { + override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { mode.menuInflater.inflate(R.menu.mode_favourites, menu) - return super.onCreateActionMode(mode, menu) + return super.onCreateActionMode(controller, mode, menu) } - override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean { + override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { menu.findItem(R.id.action_save)?.isVisible = selectedItems.none { it.source == MangaSource.LOCAL } - return super.onPrepareActionMode(mode, menu) + return super.onPrepareActionMode(controller, mode, menu) } - override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean { return when (item.itemId) { R.id.action_remove -> { viewModel.removeFromFavourites(selectedItemsIds) mode.finish() true } - else -> super.onActionItemClicked(mode, item) + else -> super.onActionItemClicked(controller, mode, item) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt index 11d3f75ba..bb7b984aa 100644 --- a/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/history/ui/HistoryListFragment.kt @@ -8,6 +8,7 @@ import androidx.appcompat.view.ActionMode import org.koin.android.ext.android.get import org.koin.androidx.viewmodel.ext.android.viewModel import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.list.ListSelectionController import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.utils.ext.addMenuProvider @@ -27,26 +28,26 @@ class HistoryListFragment : MangaListFragment() { override fun onScrolledToEnd() = Unit - override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { + override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { mode.menuInflater.inflate(R.menu.mode_history, menu) - return super.onCreateActionMode(mode, menu) + return super.onCreateActionMode(controller, mode, menu) } - override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean { + override fun onPrepareActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { menu.findItem(R.id.action_save)?.isVisible = selectedItems.none { it.source == MangaSource.LOCAL } - return super.onPrepareActionMode(mode, menu) + return super.onPrepareActionMode(controller, mode, menu) } - override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean { return when (item.itemId) { R.id.action_remove -> { viewModel.removeFromHistory(selectedItemsIds) mode.finish() true } - else -> super.onActionItemClicked(mode, item) + else -> super.onActionItemClicked(controller, mode, item) } } diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt index 9dcce6ba6..1cd0816df 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListFragment.kt @@ -53,13 +53,13 @@ abstract class MangaListFragment : PaginationScrollListener.Callback, MangaListListener, SwipeRefreshLayout.OnRefreshListener, - ListSelectionController.Callback, + ListSelectionController.Callback2, FastScroller.FastScrollListener { private var listAdapter: MangaListAdapter? = null private var paginationListener: PaginationScrollListener? = null private var selectionController: ListSelectionController? = null - private val spanResolver = MangaListSpanResolver() + private var spanResolver: MangaListSpanResolver? = null private val spanSizeLookup = SpanSizeLookup() private val listCommitCallback = Runnable { spanSizeLookup.invalidateCache() @@ -82,6 +82,7 @@ abstract class MangaListFragment : override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) listAdapter = onCreateAdapter() + spanResolver = MangaListSpanResolver(view.resources) selectionController = ListSelectionController( activity = requireActivity(), decoration = MangaSelectionDecoration(view.context), @@ -116,6 +117,7 @@ abstract class MangaListFragment : listAdapter = null paginationListener = null selectionController = null + spanResolver = null spanSizeLookup.invalidateCache() super.onDestroyView() } @@ -230,7 +232,7 @@ abstract class MangaListFragment : private fun onGridScaleChanged(scale: Float) { spanSizeLookup.invalidateCache() - spanResolver.setGridSize(scale, binding.recyclerView) + spanResolver?.setGridSize(scale, binding.recyclerView) } private fun onListModeChanged(mode: ListMode) { @@ -255,7 +257,7 @@ abstract class MangaListFragment : addItemDecoration(SpacingItemDecoration(spacing)) } ListMode.GRID -> { - layoutManager = FitHeightGridLayoutManager(context, spanResolver.spanCount).also { + layoutManager = FitHeightGridLayoutManager(context, checkNotNull(spanResolver).spanCount).also { it.spanSizeLookup = spanSizeLookup } val spacing = resources.getDimensionPixelOffset(R.dimen.grid_spacing) @@ -268,17 +270,11 @@ abstract class MangaListFragment : } } - override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { + override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { return menu.isNotEmpty() } - @CallSuper - override fun onPrepareActionMode(mode: ActionMode, menu: Menu): Boolean { - mode.title = selectionController?.count?.toString() - return true - } - - override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { + override fun onActionItemClicked(controller: ListSelectionController, mode: ActionMode, item: MenuItem): Boolean { return when (item.itemId) { R.id.action_select_all -> { val ids = listAdapter?.items?.mapNotNull { @@ -306,7 +302,7 @@ abstract class MangaListFragment : } } - override fun onSelectionChanged(count: Int) { + override fun onSelectionChanged(controller: ListSelectionController, count: Int) { binding.recyclerView.invalidateItemDecorations() } diff --git a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListSpanResolver.kt b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListSpanResolver.kt index 1e58b2065..c3c534e8f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListSpanResolver.kt +++ b/app/src/main/java/org/koitharu/kotatsu/list/ui/MangaListSpanResolver.kt @@ -1,18 +1,22 @@ package org.koitharu.kotatsu.list.ui +import android.content.res.Resources import android.view.View import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.RecyclerView -import org.koitharu.kotatsu.R import kotlin.math.abs import kotlin.math.roundToInt +import org.koitharu.kotatsu.R -class MangaListSpanResolver : View.OnLayoutChangeListener { +class MangaListSpanResolver( + resources: Resources, +) : View.OnLayoutChangeListener { var spanCount = 3 private set - private var gridWidth = -1f + private val gridWidth = resources.getDimension(R.dimen.preferred_grid_width) + private val spacing = resources.getDimension(R.dimen.grid_spacing) private var cellWidth = -1f override fun onLayoutChange( @@ -24,15 +28,12 @@ class MangaListSpanResolver : View.OnLayoutChangeListener { oldLeft: Int, oldTop: Int, oldRight: Int, - oldBottom: Int + oldBottom: Int, ) { if (cellWidth <= 0f) { return } val rv = v as? RecyclerView ?: return - if (gridWidth < 0f) { - gridWidth = rv.resources.getDimension(R.dimen.preferred_grid_width) - } val width = abs(right - left) if (width == 0) { return @@ -41,17 +42,13 @@ class MangaListSpanResolver : View.OnLayoutChangeListener { (rv.layoutManager as? GridLayoutManager)?.spanCount = spanCount } - fun setGridSize(scaleFactor: Float, rv: RecyclerView?) { - if (gridWidth < 0f) { - gridWidth = (rv ?: return).resources.getDimension(R.dimen.preferred_grid_width) - } - cellWidth = gridWidth * scaleFactor - if (rv != null) { - val width = rv.width - if (width != 0) { - resolveGridSpanCount(width) - (rv.layoutManager as? GridLayoutManager)?.spanCount = spanCount - } + fun setGridSize(scaleFactor: Float, rv: RecyclerView) { + cellWidth = (gridWidth * scaleFactor) + spacing + val lm = rv.layoutManager as? GridLayoutManager ?: return + val innerWidth = lm.width - lm.paddingEnd - lm.paddingStart + if (innerWidth > 0) { + resolveGridSpanCount(innerWidth) + lm.spanCount = spanCount } } @@ -59,4 +56,4 @@ class MangaListSpanResolver : View.OnLayoutChangeListener { val estimatedCount = (width / cellWidth).roundToInt() spanCount = estimatedCount.coerceAtLeast(2) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListFragment.kt index 4fff18ac6..351f8d58d 100644 --- a/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/local/ui/LocalListFragment.kt @@ -15,6 +15,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.snackbar.Snackbar import org.koin.androidx.viewmodel.ext.android.viewModel import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.list.ListSelectionController import org.koitharu.kotatsu.download.ui.service.DownloadService import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.utils.ShareHelper @@ -27,7 +28,7 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback() private val importCall = registerForActivityResult( ActivityResultContracts.OpenMultipleDocuments(), - this + this, ) private var importSnackbar: Snackbar? = null private val downloadReceiver = object : BroadcastReceiver() { @@ -42,7 +43,7 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback { showDeletionConfirm(selectedItemsIds, mode) @@ -100,7 +101,7 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback super.onActionItemClicked(mode, item) + else -> super.onActionItemClicked(controller, mode, item) } } @@ -143,4 +144,4 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback { private lateinit var thumbnails: List - private val spanResolver = MangaListSpanResolver() + private var spanResolver: MangaListSpanResolver? = null private var currentPageIndex = -1 private var pageLoader: PageLoader? = null @@ -51,7 +51,7 @@ class PagesThumbnailsSheet : number = i + 1, isCurrent = i == currentPageIndex, repository = repository, - page = x + page = x, ) } } @@ -78,17 +78,17 @@ class PagesThumbnailsSheet : with(binding.recyclerView) { addItemDecoration( - SpacingItemDecoration(resources.getDimensionPixelOffset(R.dimen.grid_spacing)) + SpacingItemDecoration(resources.getDimensionPixelOffset(R.dimen.grid_spacing)), ) adapter = PageThumbnailAdapter( dataSet = thumbnails, coil = get(), scope = viewLifecycleScope, loader = getPageLoader(), - clickListener = this@PagesThumbnailsSheet + clickListener = this@PagesThumbnailsSheet, ) addOnLayoutChangeListener(spanResolver) - spanResolver.setGridSize(get().gridSize / 100f, this) + spanResolver?.setGridSize(get().gridSize / 100f, this) if (currentPageIndex > 0) { val offset = resources.getDimensionPixelOffset(R.dimen.preferred_grid_width) (layoutManager as GridLayoutManager).scrollToPositionWithOffset(currentPageIndex, offset) @@ -98,6 +98,7 @@ class PagesThumbnailsSheet : override fun onDestroyView() { super.onDestroyView() + spanResolver = null pageLoader?.close() pageLoader = null } @@ -124,7 +125,7 @@ class PagesThumbnailsSheet : toolbar.subtitle = resources.getQuantityString( R.plurals.pages, thumbnails.size, - thumbnails.size + thumbnails.size, ) } else { toolbar.subtitle = null @@ -147,4 +148,4 @@ class PagesThumbnailsSheet : putInt(ARG_CURRENT, currentPage) }.show(fm, TAG) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt index 23218082d..d7ac7a8bf 100644 --- a/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/remotelist/ui/RemoteListFragment.kt @@ -11,6 +11,7 @@ import androidx.core.view.MenuProvider import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.core.parameter.parametersOf import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.list.ListSelectionController import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.list.ui.filter.FilterBottomSheet import org.koitharu.kotatsu.main.ui.AppBarOwner @@ -38,9 +39,9 @@ class RemoteListFragment : MangaListFragment() { viewModel.loadNextPage() } - override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { + override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { mode.menuInflater.inflate(R.menu.mode_remote, menu) - return super.onCreateActionMode(mode, menu) + return super.onCreateActionMode(controller, mode, menu) } override fun onFilterClick(view: View?) { @@ -51,7 +52,9 @@ class RemoteListFragment : MangaListFragment() { viewModel.resetFilter() } - private inner class RemoteListMenuProvider : MenuProvider, SearchView.OnQueryTextListener, + private inner class RemoteListMenuProvider : + MenuProvider, + SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener { override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) { diff --git a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt index 6aec88710..ebfb1ace0 100644 --- a/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/search/ui/SearchFragment.kt @@ -5,6 +5,7 @@ import androidx.appcompat.view.ActionMode import org.koin.androidx.viewmodel.ext.android.viewModel import org.koin.core.parameter.parametersOf import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.list.ListSelectionController import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.parsers.model.MangaSource import org.koitharu.kotatsu.utils.ext.serializableArgument @@ -24,9 +25,9 @@ class SearchFragment : MangaListFragment() { viewModel.loadNextPage() } - override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { + override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { mode.menuInflater.inflate(R.menu.mode_remote, menu) - return super.onCreateActionMode(mode, menu) + return super.onCreateActionMode(controller, mode, menu) } companion object { @@ -39,4 +40,4 @@ class SearchFragment : MangaListFragment() { putString(ARG_QUERY, query) } } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt b/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt index f1af41bf3..2c03fca6f 100644 --- a/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt +++ b/app/src/main/java/org/koitharu/kotatsu/suggestions/ui/SuggestionsFragment.kt @@ -10,6 +10,7 @@ import androidx.core.view.MenuProvider import com.google.android.material.snackbar.Snackbar import org.koin.androidx.viewmodel.ext.android.viewModel import org.koitharu.kotatsu.R +import org.koitharu.kotatsu.base.ui.list.ListSelectionController import org.koitharu.kotatsu.list.ui.MangaListFragment import org.koitharu.kotatsu.settings.SettingsActivity import org.koitharu.kotatsu.utils.ext.addMenuProvider @@ -26,9 +27,9 @@ class SuggestionsFragment : MangaListFragment() { override fun onScrolledToEnd() = Unit - override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean { + override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean { mode.menuInflater.inflate(R.menu.mode_remote, menu) - return super.onCreateActionMode(mode, menu) + return super.onCreateActionMode(controller, mode, menu) } private inner class SuggestionMenuProvider : MenuProvider { @@ -59,4 +60,4 @@ class SuggestionsFragment : MangaListFragment() { fun newInstance() = SuggestionsFragment() } -} \ No newline at end of file +}