UI improvements
parent
7c4b254f08
commit
265fbc9f63
@ -0,0 +1,126 @@
|
|||||||
|
package org.koitharu.kotatsu.details.ui
|
||||||
|
|
||||||
|
import android.view.Menu
|
||||||
|
import android.view.MenuInflater
|
||||||
|
import android.view.MenuItem
|
||||||
|
import androidx.activity.OnBackPressedCallback
|
||||||
|
import androidx.appcompat.widget.SearchView
|
||||||
|
import androidx.core.view.MenuProvider
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import com.google.android.material.slider.LabelFormatter
|
||||||
|
import com.google.android.material.slider.Slider
|
||||||
|
import org.koitharu.kotatsu.R
|
||||||
|
import org.koitharu.kotatsu.core.prefs.AppSettings
|
||||||
|
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
|
||||||
|
import org.koitharu.kotatsu.core.util.ext.setValueRounded
|
||||||
|
import org.koitharu.kotatsu.core.util.progress.IntPercentLabelFormatter
|
||||||
|
import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesSheet.Companion.TAB_CHAPTERS
|
||||||
|
import org.koitharu.kotatsu.details.ui.pager.ChaptersPagesSheet.Companion.TAB_PAGES
|
||||||
|
import java.lang.ref.WeakReference
|
||||||
|
|
||||||
|
class ChapterPagesMenuProvider(
|
||||||
|
private val viewModel: DetailsViewModel,
|
||||||
|
private val sheet: BaseAdaptiveSheet<*>,
|
||||||
|
private val pager: ViewPager2,
|
||||||
|
private val settings: AppSettings,
|
||||||
|
) : OnBackPressedCallback(false), MenuProvider, SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener,
|
||||||
|
Slider.OnChangeListener {
|
||||||
|
|
||||||
|
private var expandedItemRef: WeakReference<MenuItem>? = null
|
||||||
|
|
||||||
|
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
||||||
|
val tab = getCurrentTab()
|
||||||
|
when (tab) {
|
||||||
|
TAB_CHAPTERS -> {
|
||||||
|
menuInflater.inflate(R.menu.opt_chapters, menu)
|
||||||
|
menu.findItem(R.id.action_search)?.run {
|
||||||
|
setOnActionExpandListener(this@ChapterPagesMenuProvider)
|
||||||
|
(actionView as? SearchView)?.setupChaptersSearchView()
|
||||||
|
}
|
||||||
|
menu.findItem(R.id.action_search)?.isVisible = viewModel.isChaptersEmpty.value == false
|
||||||
|
menu.findItem(R.id.action_reversed)?.isChecked = viewModel.isChaptersReversed.value == true
|
||||||
|
menu.findItem(R.id.action_grid_view)?.isChecked = viewModel.isChaptersInGridView.value == true
|
||||||
|
}
|
||||||
|
|
||||||
|
TAB_PAGES -> {
|
||||||
|
menuInflater.inflate(R.menu.opt_pages, menu)
|
||||||
|
menu.findItem(R.id.action_grid_size)?.run {
|
||||||
|
setOnActionExpandListener(this@ChapterPagesMenuProvider)
|
||||||
|
(actionView as? Slider)?.setupPagesSizeSlider()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) {
|
||||||
|
R.id.action_reversed -> {
|
||||||
|
viewModel.setChaptersReversed(!menuItem.isChecked)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
R.id.action_grid_view -> {
|
||||||
|
viewModel.setChaptersInGridView(!menuItem.isChecked)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun handleOnBackPressed() {
|
||||||
|
expandedItemRef?.get()?.collapseActionView()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
|
||||||
|
expandedItemRef = WeakReference(item)
|
||||||
|
sheet.expandAndLock()
|
||||||
|
isEnabled = true
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
|
||||||
|
expandedItemRef = null
|
||||||
|
isEnabled = false
|
||||||
|
(item.actionView as? SearchView)?.setQuery("", false)
|
||||||
|
viewModel.performChapterSearch(null)
|
||||||
|
sheet.unlock()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onQueryTextSubmit(query: String?): Boolean = false
|
||||||
|
|
||||||
|
override fun onQueryTextChange(newText: String?): Boolean {
|
||||||
|
viewModel.performChapterSearch(newText)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onValueChange(slider: Slider, value: Float, fromUser: Boolean) {
|
||||||
|
if (fromUser) {
|
||||||
|
settings.gridSizePages = value.toInt()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun SearchView.setupChaptersSearchView() {
|
||||||
|
setOnQueryTextListener(this@ChapterPagesMenuProvider)
|
||||||
|
setIconifiedByDefault(false)
|
||||||
|
queryHint = context.getString(R.string.search_chapters)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Slider.setupPagesSizeSlider() {
|
||||||
|
valueFrom = 50f
|
||||||
|
valueTo = 150f
|
||||||
|
stepSize = 5f
|
||||||
|
isTickVisible = false
|
||||||
|
labelBehavior = LabelFormatter.LABEL_FLOATING
|
||||||
|
setLabelFormatter(IntPercentLabelFormatter(context))
|
||||||
|
setValueRounded(settings.gridSizePages.toFloat())
|
||||||
|
addOnChangeListener(this@ChapterPagesMenuProvider)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getCurrentTab(): Int {
|
||||||
|
var page = pager.currentItem
|
||||||
|
if (page > 0 && pager.adapter?.itemCount == 2) { // no Pages page
|
||||||
|
page++ // shift
|
||||||
|
}
|
||||||
|
return page
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,75 +0,0 @@
|
|||||||
package org.koitharu.kotatsu.details.ui
|
|
||||||
|
|
||||||
import android.view.Menu
|
|
||||||
import android.view.MenuInflater
|
|
||||||
import android.view.MenuItem
|
|
||||||
import androidx.activity.OnBackPressedCallback
|
|
||||||
import androidx.appcompat.widget.SearchView
|
|
||||||
import androidx.core.view.MenuProvider
|
|
||||||
import org.koitharu.kotatsu.R
|
|
||||||
import org.koitharu.kotatsu.core.ui.sheet.BaseAdaptiveSheet
|
|
||||||
import java.lang.ref.WeakReference
|
|
||||||
|
|
||||||
class ChaptersMenuProvider2(
|
|
||||||
private val viewModel: DetailsViewModel,
|
|
||||||
private val sheet: BaseAdaptiveSheet<*>,
|
|
||||||
) : OnBackPressedCallback(false), MenuProvider, SearchView.OnQueryTextListener, MenuItem.OnActionExpandListener {
|
|
||||||
|
|
||||||
private var searchItemRef: WeakReference<MenuItem>? = null
|
|
||||||
|
|
||||||
override fun onCreateMenu(menu: Menu, menuInflater: MenuInflater) {
|
|
||||||
menuInflater.inflate(R.menu.opt_chapters, menu)
|
|
||||||
val searchMenuItem = menu.findItem(R.id.action_search)
|
|
||||||
searchMenuItem.setOnActionExpandListener(this)
|
|
||||||
val searchView = searchMenuItem.actionView as SearchView
|
|
||||||
searchView.setOnQueryTextListener(this)
|
|
||||||
searchView.setIconifiedByDefault(false)
|
|
||||||
searchView.queryHint = searchMenuItem.title
|
|
||||||
searchItemRef = WeakReference(searchMenuItem)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPrepareMenu(menu: Menu) {
|
|
||||||
menu.findItem(R.id.action_search)?.isVisible = viewModel.isChaptersEmpty.value == false
|
|
||||||
menu.findItem(R.id.action_reversed)?.isChecked = viewModel.isChaptersReversed.value == true
|
|
||||||
menu.findItem(R.id.action_grid_view)?.isChecked = viewModel.isChaptersInGridView.value == true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMenuItemSelected(menuItem: MenuItem): Boolean = when (menuItem.itemId) {
|
|
||||||
R.id.action_reversed -> {
|
|
||||||
viewModel.setChaptersReversed(!menuItem.isChecked)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
R.id.action_grid_view -> {
|
|
||||||
viewModel.setChaptersInGridView(!menuItem.isChecked)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun handleOnBackPressed() {
|
|
||||||
searchItemRef?.get()?.collapseActionView()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMenuItemActionExpand(item: MenuItem): Boolean {
|
|
||||||
sheet.expandAndLock()
|
|
||||||
isEnabled = true
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onMenuItemActionCollapse(item: MenuItem): Boolean {
|
|
||||||
isEnabled = false
|
|
||||||
(item.actionView as? SearchView)?.setQuery("", false)
|
|
||||||
viewModel.performChapterSearch(null)
|
|
||||||
sheet.unlock()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onQueryTextSubmit(query: String?): Boolean = false
|
|
||||||
|
|
||||||
override fun onQueryTextChange(newText: String?): Boolean {
|
|
||||||
viewModel.performChapterSearch(newText)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,59 @@
|
|||||||
|
package org.koitharu.kotatsu.details.ui.pager.pages
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
class PagesGridSpanResolver(
|
||||||
|
resources: Resources,
|
||||||
|
) : View.OnLayoutChangeListener {
|
||||||
|
|
||||||
|
var spanCount = 3
|
||||||
|
private set
|
||||||
|
|
||||||
|
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(
|
||||||
|
v: View?,
|
||||||
|
left: Int,
|
||||||
|
top: Int,
|
||||||
|
right: Int,
|
||||||
|
bottom: Int,
|
||||||
|
oldLeft: Int,
|
||||||
|
oldTop: Int,
|
||||||
|
oldRight: Int,
|
||||||
|
oldBottom: Int,
|
||||||
|
) {
|
||||||
|
if (cellWidth <= 0f) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
val rv = v as? RecyclerView ?: return
|
||||||
|
val width = abs(right - left)
|
||||||
|
if (width == 0) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun resolveGridSpanCount(width: Int) {
|
||||||
|
val estimatedCount = (width / cellWidth).roundToInt()
|
||||||
|
spanCount = estimatedCount.coerceAtLeast(2)
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<vector
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="24dp"
|
||||||
|
android:height="24dp"
|
||||||
|
android:tint="?colorControlNormal"
|
||||||
|
android:viewportWidth="24"
|
||||||
|
android:viewportHeight="24">
|
||||||
|
<path
|
||||||
|
android:fillColor="#000"
|
||||||
|
android:pathData="M12 18.88A1 1 0 0 1 11.71 19.71A1 1 0 0 1 10.3 19.71L6.3 15.71A1 1 0 0 1 6 14.87V9.75L1.21 3.62A1 1 0 0 1 1.38 2.22A1 1 0 0 1 2 2H16A1 1 0 0 1 16.62 2.22A1 1 0 0 1 16.79 3.62L12 9.75V18.88M4 4L8 9.06V14.58L10 16.58V9.05L14 4M13 16L18 21L23 16Z" />
|
||||||
|
</vector>
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/action_grid_size"
|
||||||
|
android:icon="@drawable/ic_size_large"
|
||||||
|
android:orderInCategory="10"
|
||||||
|
android:title="@string/grid_size"
|
||||||
|
app:actionViewClass="com.google.android.material.slider.Slider"
|
||||||
|
app:showAsAction="ifRoom|collapseActionView" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
Loading…
Reference in New Issue