mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-11-09 19:55:11 +01:00
Using a seekbar to select grid size
This is mostly the same amount of options for phones, but opens more for tablets There's also actual math now for setting the grid size and a float used (rounded to the nearest .25) I could just add back portrait/landscape per row....I could but This seeker also has a bubble tooltip to show the current value, might use elsewhere later
This commit is contained in:
parent
4cbf1cc785
commit
0cf56ca335
@ -110,6 +110,25 @@ object Migrations {
|
||||
remove("enable_doh")
|
||||
}
|
||||
}
|
||||
|
||||
val oldGridSize = prefs.getInt("grid_size", -1)
|
||||
// Migrate to float for grid size
|
||||
if (oldGridSize != -1) {
|
||||
prefs.edit {
|
||||
putFloat(
|
||||
PreferenceKeys.gridSize,
|
||||
when (oldGridSize) {
|
||||
4 -> 3f
|
||||
3 -> 1.5f
|
||||
2 -> 1f
|
||||
1 -> 0f
|
||||
0 -> -.5f
|
||||
else -> .5f
|
||||
}
|
||||
)
|
||||
remove("grid_size")
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
@ -150,7 +150,7 @@ object PreferenceKeys {
|
||||
|
||||
const val libraryLayout = "pref_display_library_layout"
|
||||
|
||||
const val gridSize = "grid_size"
|
||||
const val gridSize = "grid_size_float"
|
||||
|
||||
const val uniformGrid = "uniform_grid"
|
||||
|
||||
|
@ -242,7 +242,7 @@ class PreferencesHelper(val context: Context) {
|
||||
|
||||
fun libraryLayout() = flowPrefs.getInt(Keys.libraryLayout, 2)
|
||||
|
||||
fun gridSize() = flowPrefs.getInt(Keys.gridSize, 2)
|
||||
fun gridSize() = flowPrefs.getFloat(Keys.gridSize, 1f)
|
||||
|
||||
fun uniformGrid() = flowPrefs.getBoolean(Keys.uniformGrid, true)
|
||||
|
||||
|
@ -794,13 +794,7 @@ class LibraryController(
|
||||
end = 0
|
||||
)
|
||||
} else {
|
||||
binding.libraryGridRecycler.recycler.columnWidth = when (preferences.gridSize().get()) {
|
||||
1 -> 1f
|
||||
2 -> 1.25f
|
||||
3 -> 1.66f
|
||||
4 -> 3f
|
||||
else -> .75f
|
||||
}
|
||||
binding.libraryGridRecycler.recycler.setGridSize(preferences)
|
||||
binding.libraryGridRecycler.recycler.updatePaddingRelative(
|
||||
start = 5.dpToPx,
|
||||
end = 5.dpToPx
|
||||
@ -809,7 +803,12 @@ class LibraryController(
|
||||
}
|
||||
|
||||
private fun setPreferenceFlows() {
|
||||
listOf(preferences.libraryLayout(), preferences.uniformGrid(), preferences.gridSize(), preferences.unreadBadgeType()).forEach {
|
||||
listOf(
|
||||
preferences.libraryLayout(),
|
||||
preferences.uniformGrid(),
|
||||
preferences.gridSize(),
|
||||
preferences.unreadBadgeType()
|
||||
).forEach {
|
||||
it.asFlow()
|
||||
.drop(1)
|
||||
.onEach {
|
||||
|
@ -1,10 +1,24 @@
|
||||
package eu.kanade.tachiyomi.ui.library.display
|
||||
|
||||
import android.animation.ValueAnimator
|
||||
import android.content.Context
|
||||
import android.text.Spannable
|
||||
import android.text.SpannableStringBuilder
|
||||
import android.text.style.ForegroundColorSpan
|
||||
import android.util.AttributeSet
|
||||
import android.view.ViewTreeObserver
|
||||
import android.widget.SeekBar
|
||||
import androidx.core.animation.addListener
|
||||
import androidx.core.view.isVisible
|
||||
import eu.kanade.tachiyomi.R
|
||||
import eu.kanade.tachiyomi.databinding.LibraryDisplayLayoutBinding
|
||||
import eu.kanade.tachiyomi.util.bindToPreference
|
||||
import eu.kanade.tachiyomi.util.system.dpToPx
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.view.rowsForValue
|
||||
import eu.kanade.tachiyomi.widget.BaseLibraryDisplayView
|
||||
import eu.kanade.tachiyomi.widget.EndAnimatorListener
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class LibraryDisplayView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
BaseLibraryDisplayView<LibraryDisplayLayoutBinding>(context, attrs) {
|
||||
@ -13,6 +27,93 @@ class LibraryDisplayView @JvmOverloads constructor(context: Context, attrs: Attr
|
||||
override fun initGeneralPreferences() {
|
||||
binding.displayGroup.bindToPreference(preferences.libraryLayout())
|
||||
binding.uniformGrid.bindToPreference(preferences.uniformGrid())
|
||||
binding.gridSizeToggleGroup.bindToPreference(preferences.gridSize())
|
||||
binding.gridSeekbar.progress = ((preferences.gridSize().get() + .5f) * 2f).roundToInt()
|
||||
binding.resetGridSize.setOnClickListener {
|
||||
binding.gridSeekbar.progress = 3
|
||||
}
|
||||
binding.root.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
|
||||
override fun onGlobalLayout() {
|
||||
if (binding.root.width > 0) {
|
||||
setGridText(binding.gridSeekbar.progress)
|
||||
binding.root.viewTreeObserver.removeOnGlobalLayoutListener(this)
|
||||
}
|
||||
}
|
||||
})
|
||||
binding.gridSeekbar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
|
||||
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
|
||||
if (seekBar != null && fromUser) {
|
||||
alpha = 1f
|
||||
isVisible = true
|
||||
adjustSeekBarTip(seekBar, progress)
|
||||
}
|
||||
if (!fromUser) {
|
||||
preferences.gridSize().set((progress / 2f) - .5f)
|
||||
}
|
||||
setGridText(progress)
|
||||
}
|
||||
|
||||
override fun onStartTrackingTouch(seekBar: SeekBar?) {
|
||||
with(binding.seekBarTextView.root) {
|
||||
alpha = 0f
|
||||
isVisible = true
|
||||
animate().alpha(1f).setDuration(250L).start()
|
||||
seekBar?.post {
|
||||
adjustSeekBarTip(seekBar, seekBar.progress)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStopTrackingTouch(seekBar: SeekBar?) {
|
||||
preferences.gridSize().set(((seekBar?.progress ?: 2) / 2f) - .5f)
|
||||
with(binding.seekBarTextView.root) {
|
||||
isVisible = true
|
||||
alpha = 1f
|
||||
post {
|
||||
val anim =
|
||||
ValueAnimator.ofFloat(
|
||||
1f,
|
||||
0f
|
||||
) // animate().alpha(0f).setDuration(250L)
|
||||
anim.duration = 250
|
||||
anim.startDelay = 500
|
||||
anim.addUpdateListener {
|
||||
alpha = it.animatedValue as Float
|
||||
}
|
||||
anim.addListener {
|
||||
EndAnimatorListener {
|
||||
isVisible = false
|
||||
}
|
||||
}
|
||||
anim.start()
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun setGridText(progress: Int) {
|
||||
with(binding.gridSizeText) {
|
||||
val rows = this@LibraryDisplayView.rowsForValue(progress)
|
||||
val titleText = context.getString(R.string.grid_size)
|
||||
val subtitleText = context.getString(R.string._per_row, rows)
|
||||
val spannable = SpannableStringBuilder(titleText + "\n" + subtitleText)
|
||||
spannable.setSpan(
|
||||
ForegroundColorSpan(context.getResourceColor(android.R.attr.textColorSecondary)),
|
||||
titleText.length + 1,
|
||||
spannable.length,
|
||||
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
|
||||
)
|
||||
text = spannable
|
||||
}
|
||||
}
|
||||
|
||||
private fun adjustSeekBarTip(seekBar: SeekBar, progress: Int) {
|
||||
with(binding.seekBarTextView.root) {
|
||||
val value =
|
||||
(progress * (seekBar.width - 12.dpToPx - 2 * seekBar.thumbOffset)) / seekBar.max
|
||||
text = this@LibraryDisplayView.rowsForValue(progress).toString()
|
||||
x = seekBar.x + value + seekBar.thumbOffset / 2 + 5.dpToPx
|
||||
y = seekBar.y + binding.gridSizeLayout.y - 6.dpToPx - height
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import eu.kanade.tachiyomi.data.preference.getOrDefault
|
||||
import eu.kanade.tachiyomi.ui.library.LibraryController
|
||||
import eu.kanade.tachiyomi.ui.setting.SettingsLibraryController
|
||||
import eu.kanade.tachiyomi.util.view.compatToolTipText
|
||||
import eu.kanade.tachiyomi.util.view.visible
|
||||
import eu.kanade.tachiyomi.util.view.withFadeTransaction
|
||||
import eu.kanade.tachiyomi.widget.TabbedBottomSheetDialog
|
||||
import uy.kohesive.injekt.Injekt
|
||||
|
@ -167,13 +167,7 @@ open class BrowseSourceController(bundle: Bundle) :
|
||||
}
|
||||
} else {
|
||||
(binding.catalogueView.inflate(R.layout.manga_recycler_autofit) as AutofitRecyclerView).apply {
|
||||
columnWidth = when (preferences.gridSize().get()) {
|
||||
1 -> 1f
|
||||
2 -> 1.25f
|
||||
3 -> 1.66f
|
||||
4 -> 3f
|
||||
else -> .75f
|
||||
}
|
||||
setGridSize(preferences)
|
||||
|
||||
(layoutManager as androidx.recyclerview.widget.GridLayoutManager).spanSizeLookup = object : androidx.recyclerview.widget.GridLayoutManager.SpanSizeLookup() {
|
||||
override fun getSpanSize(position: Int): Int {
|
||||
|
@ -37,8 +37,13 @@ import eu.kanade.tachiyomi.util.system.ThemeUtil
|
||||
import eu.kanade.tachiyomi.util.system.contextCompatColor
|
||||
import eu.kanade.tachiyomi.util.system.getPrefTheme
|
||||
import eu.kanade.tachiyomi.util.system.getResourceColor
|
||||
import eu.kanade.tachiyomi.util.system.pxToDp
|
||||
import eu.kanade.tachiyomi.widget.AutofitRecyclerView
|
||||
import uy.kohesive.injekt.Injekt
|
||||
import uy.kohesive.injekt.api.get
|
||||
import kotlin.math.max
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
/**
|
||||
* Returns coordinates of view.
|
||||
@ -338,6 +343,17 @@ fun RecyclerView.smoothScrollToTop() {
|
||||
}
|
||||
}
|
||||
|
||||
fun View.rowsForValue(value: Int): Int {
|
||||
return rowsForValue((value / 2f) - .5f)
|
||||
}
|
||||
|
||||
fun View.rowsForValue(value: Float): Int {
|
||||
val size = 1.5f.pow(value)
|
||||
val trueSize = AutofitRecyclerView.MULTIPLE * ((size * 100 / AutofitRecyclerView.MULTIPLE).roundToInt()) / 100f
|
||||
val dpWidth = (measuredWidth.pxToDp / 100f).roundToInt()
|
||||
return max(1, (dpWidth / trueSize).roundToInt())
|
||||
}
|
||||
|
||||
var View.compatToolTipText: CharSequence?
|
||||
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||
tooltipText
|
||||
|
@ -3,8 +3,10 @@ package eu.kanade.tachiyomi.widget
|
||||
import android.content.Context
|
||||
import android.util.AttributeSet
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
import eu.kanade.tachiyomi.data.preference.PreferencesHelper
|
||||
import eu.kanade.tachiyomi.util.system.pxToDp
|
||||
import kotlin.math.max
|
||||
import kotlin.math.pow
|
||||
import kotlin.math.roundToInt
|
||||
|
||||
class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
|
||||
@ -51,6 +53,12 @@ class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
setSpan()
|
||||
}
|
||||
|
||||
fun setGridSize(preferences: PreferencesHelper) {
|
||||
val size = 1.5f.pow(preferences.gridSize().get())
|
||||
val trueSize = MULTIPLE * ((size * 100 / MULTIPLE).roundToInt()) / 100f
|
||||
columnWidth = trueSize
|
||||
}
|
||||
|
||||
private fun setSpan(force: Boolean = false) {
|
||||
if ((spanCount == 0 || force) && columnWidth > 0) {
|
||||
val dpWidth = (measuredWidth.pxToDp / 100f).roundToInt()
|
||||
@ -58,4 +66,9 @@ class AutofitRecyclerView @JvmOverloads constructor(context: Context, attrs: Att
|
||||
spanCount = count
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val MULTIPLE_PERCENT = 0.25f
|
||||
const val MULTIPLE = MULTIPLE_PERCENT * 100
|
||||
}
|
||||
}
|
||||
|
9
app/src/main/res/drawable/ic_rounded_tooltip_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_rounded_tooltip_24dp.xml
Normal file
@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportWidth="24"
|
||||
android:viewportHeight="24">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,3.6c-3.9,0 -7,3.1 -7,7c0,5.2 7,9.8 7,9.8s7,-4.5 7,-9.8C19,6.7 15.9,3.6 12,3.6z"/>
|
||||
</vector>
|
@ -1,9 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<eu.kanade.tachiyomi.ui.library.display.LibraryDisplayView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="match_parent"
|
||||
<eu.kanade.tachiyomi.ui.library.display.LibraryDisplayView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:orientation="vertical">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/display_frame_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/linear_layout"
|
||||
android:orientation="vertical"
|
||||
@ -34,53 +41,55 @@
|
||||
android:text="@string/comfortable_grid" />
|
||||
</RadioGroup>
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
style="@style/TextAppearance.MaterialComponents.Headline6"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/grid_size_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="12dp"
|
||||
android:text="@string/grid_options" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/grid_size_toggle_group"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:layout_marginStart="16dp"
|
||||
android:gravity="center"
|
||||
android:orientation="horizontal">
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/grid_size_text"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/grid_seekbar"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
android:textAppearance="@style/TextAppearance.Regular.Body1"
|
||||
android:textSize="15sp"
|
||||
android:text="@string/grid_size"
|
||||
android:layout_weight="0"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/x_small" />
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
<SeekBar
|
||||
android:id="@+id/grid_seekbar"
|
||||
android:layout_marginStart="12dp"
|
||||
android:paddingTop="6dp"
|
||||
android:paddingBottom="6dp"
|
||||
android:max="7"
|
||||
android:layout_width="0dp"
|
||||
app:layout_constraintStart_toEndOf="@id/grid_size_text"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/reset_grid_size"
|
||||
app:layout_constraintWidth_max="350dp"
|
||||
android:layout_height="wrap_content"/>
|
||||
|
||||
android:text="@string/small" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
<com.google.android.material.button.MaterialButton
|
||||
android:id="@+id/reset_grid_size"
|
||||
android:layout_marginStart="8dp"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/medium" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/large" />
|
||||
|
||||
<com.google.android.material.radiobutton.MaterialRadioButton
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:text="@string/x_large" />
|
||||
</RadioGroup>
|
||||
app:layout_constraintStart_toEndOf="@id/grid_seekbar"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
style="@style/Theme.Widget.Button.TextButton"
|
||||
android:text="@string/reset" />
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/uniform_grid"
|
||||
@ -88,6 +97,15 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="12dp"
|
||||
android:layout_marginEnd="12dp"
|
||||
android:text="@string/uniform_covers" />
|
||||
android:text="@string/uniform_grid_covers" />
|
||||
</LinearLayout>
|
||||
|
||||
<include
|
||||
android:id="@+id/seek_bar_text_view"
|
||||
android:visibility="gone"
|
||||
android:alpha="0"
|
||||
tools:alpha="1"
|
||||
tools:visibility="visible"
|
||||
layout="@layout/tooltip_text_view"/>
|
||||
</FrameLayout>
|
||||
</eu.kanade.tachiyomi.ui.library.display.LibraryDisplayView>
|
13
app/src/main/res/layout/tooltip_text_view.xml
Normal file
13
app/src/main/res/layout/tooltip_text_view.xml
Normal file
@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="45sp"
|
||||
android:layout_height="45sp"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
|
||||
tools:text="1"
|
||||
android:elevation="6dp"
|
||||
android:textAlignment="center"
|
||||
android:paddingTop="8dp"
|
||||
android:textColor="?colorOnAccent"
|
||||
android:backgroundTint="?colorAccent"
|
||||
android:background="@drawable/ic_rounded_tooltip_24dp" />
|
@ -154,12 +154,14 @@
|
||||
<string name="hide_start_reading_button">Hide start reading button</string>
|
||||
<string name="badges">Badges</string>
|
||||
<string name="uniform_covers">Uniform covers</string>
|
||||
<string name="uniform_grid_covers">Uniform grid covers</string>
|
||||
<string name="grid_size">Grid size</string>
|
||||
<string name="x_small">XS</string>
|
||||
<string name="small">S</string>
|
||||
<string name="medium">M</string>
|
||||
<string name="large">L</string>
|
||||
<string name="x_large">XL</string>
|
||||
<string name="grid_options">Grid options</string>
|
||||
<string name="_per_row">%d per row</string>
|
||||
<string name="hide_unread_badges">Hide unread badges</string>
|
||||
<string name="show_unread_badges">Show unread badges</string>
|
||||
<string name="show_unread_count">Show unread count</string>
|
||||
|
Loading…
Reference in New Issue
Block a user