Fix grid size computing

This commit is contained in:
Koitharu
2022-07-24 15:14:03 +03:00
parent 8ab9b4d1c3
commit 802448cb5a
9 changed files with 70 additions and 68 deletions

View File

@@ -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)
}
}

View File

@@ -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)
}
}

View File

@@ -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()
}

View File

@@ -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)
}
}
}

View File

@@ -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<List<@JvmS
override val viewModel by viewModel<LocalListViewModel>()
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<List<@JvmS
super.onAttach(context)
context.registerReceiver(
downloadReceiver,
IntentFilter(DownloadService.ACTION_DOWNLOAD_COMPLETE)
IntentFilter(DownloadService.ACTION_DOWNLOAD_COMPLETE),
)
}
@@ -73,7 +74,7 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback<List<@JvmS
Snackbar.make(
binding.recyclerView,
R.string.operation_not_supported,
Snackbar.LENGTH_SHORT
Snackbar.LENGTH_SHORT,
).show()
}
}
@@ -83,12 +84,12 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback<List<@JvmS
viewModel.importFiles(result)
}
override fun onCreateActionMode(mode: ActionMode, menu: Menu): Boolean {
override fun onCreateActionMode(controller: ListSelectionController, mode: ActionMode, menu: Menu): Boolean {
mode.menuInflater.inflate(R.menu.mode_local, menu)
return super.onCreateActionMode(mode, menu)
return super.onCreateActionMode(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 -> {
showDeletionConfirm(selectedItemsIds, mode)
@@ -100,7 +101,7 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback<List<@JvmS
mode.finish()
true
}
else -> super.onActionItemClicked(mode, item)
else -> super.onActionItemClicked(controller, mode, item)
}
}
@@ -143,4 +144,4 @@ class LocalListFragment : MangaListFragment(), ActivityResultCallback<List<@JvmS
fun newInstance() = LocalListFragment()
}
}
}

View File

@@ -33,7 +33,7 @@ class PagesThumbnailsSheet :
OnListItemClickListener<MangaPage> {
private lateinit var thumbnails: List<PageThumbnail>
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<AppSettings>().gridSize / 100f, this)
spanResolver?.setGridSize(get<AppSettings>().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)
}
}
}

View File

@@ -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) {

View File

@@ -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)
}
}
}
}

View File

@@ -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()
}
}
}