Replace numberpicker with wheelpicker (#8501)

* Replace numberpicker with wheelpicker

* cleanups
This commit is contained in:
Ivan Iskandar 2022-11-12 03:02:45 +07:00 committed by GitHub
parent 3061f198e9
commit acc65529a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 101 additions and 90 deletions

View file

@ -173,6 +173,7 @@ dependencies {
implementation(compose.foundation)
implementation(compose.material3.core)
implementation(compose.material3.adapter)
implementation(compose.material.core)
implementation(compose.material.icons)
implementation(compose.animation)
implementation(compose.animation.graphics)
@ -269,7 +270,6 @@ dependencies {
implementation(libs.markwon)
implementation(libs.aboutLibraries.compose)
implementation(libs.cascade)
implementation(libs.numberpicker)
implementation(libs.bundles.voyager)
implementation(libs.wheelpicker)

View file

@ -1,13 +1,15 @@
package eu.kanade.presentation.more.settings.screen
import android.content.Context
import androidx.annotation.StringRes
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.layout.BoxWithConstraints
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.size
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
@ -21,15 +23,18 @@ import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.pluralStringResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.DpSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.util.fastMap
import androidx.core.content.ContextCompat
import cafe.adriel.voyager.navigator.currentOrThrow
import com.bluelinelabs.conductor.Router
import com.chargemap.compose.numberpicker.NumberPicker
import com.commandiron.wheel_picker_compose.WheelPicker
import eu.kanade.domain.category.interactor.GetCategories
import eu.kanade.domain.category.interactor.ResetCategoryFlags
import eu.kanade.domain.category.model.Category
@ -78,7 +83,6 @@ class SettingsLibraryScreen : SearchableSettings {
@Composable
private fun getDisplayGroup(libraryPreferences: LibraryPreferences): Preference.PreferenceGroup {
val context = LocalContext.current
val scope = rememberCoroutineScope()
val portraitColumns by libraryPreferences.portraitColumns().stateIn(scope).collectAsState()
val landscapeColumns by libraryPreferences.landscapeColumns().stateIn(scope).collectAsState()
@ -102,8 +106,8 @@ class SettingsLibraryScreen : SearchableSettings {
preferenceItems = listOf(
Preference.PreferenceItem.TextPreference(
title = stringResource(R.string.pref_library_columns),
subtitle = "${stringResource(R.string.portrait)}: ${getColumnValue(context, portraitColumns)}, " +
"${stringResource(R.string.landscape)}: ${getColumnValue(context, landscapeColumns)}",
subtitle = "${stringResource(R.string.portrait)}: ${getColumnValue(portraitColumns)}, " +
"${stringResource(R.string.landscape)}: ${getColumnValue(landscapeColumns)}",
onClick = { showDialog = true },
),
),
@ -273,7 +277,6 @@ class SettingsLibraryScreen : SearchableSettings {
onDismissRequest: () -> Unit,
onValueChanged: (portrait: Int, landscape: Int) -> Unit,
) {
val context = LocalContext.current
var portraitValue by rememberSaveable { mutableStateOf(initialPortrait) }
var landscapeValue by rememberSaveable { mutableStateOf(initialLandscape) }
@ -281,48 +284,30 @@ class SettingsLibraryScreen : SearchableSettings {
onDismissRequest = onDismissRequest,
title = { Text(text = stringResource(R.string.pref_library_columns)) },
text = {
Column {
Row {
Column(
modifier = Modifier.weight(1f),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
modifier = Modifier.weight(1f),
text = stringResource(R.string.portrait),
textAlign = TextAlign.Center,
maxLines = 1,
style = MaterialTheme.typography.labelMedium,
)
NumberPicker(
modifier = Modifier
.fillMaxWidth()
.clipToBounds(),
value = portraitValue,
onValueChange = { portraitValue = it },
range = 0..10,
label = { getColumnValue(context, it) },
dividersColor = MaterialTheme.colorScheme.primary,
textStyle = LocalTextStyle.current.copy(color = MaterialTheme.colorScheme.onSurface),
)
}
Column(
modifier = Modifier.weight(1f),
horizontalAlignment = Alignment.CenterHorizontally,
) {
Text(
modifier = Modifier.weight(1f),
text = stringResource(R.string.landscape),
textAlign = TextAlign.Center,
maxLines = 1,
style = MaterialTheme.typography.labelMedium,
)
NumberPicker(
modifier = Modifier
.fillMaxWidth()
.clipToBounds(),
value = landscapeValue,
onValueChange = { landscapeValue = it },
range = 0..10,
label = { getColumnValue(context, it) },
dividersColor = MaterialTheme.colorScheme.primary,
textStyle = LocalTextStyle.current.copy(color = MaterialTheme.colorScheme.onSurface),
)
}
LibraryColumnsPicker(
modifier = Modifier.fillMaxWidth(),
portraitValue = portraitValue,
onPortraitChange = { portraitValue = it },
landscapeValue = landscapeValue,
onLandscapeChange = { landscapeValue = it },
)
}
},
dismissButton = {
@ -338,9 +323,78 @@ class SettingsLibraryScreen : SearchableSettings {
)
}
private fun getColumnValue(context: Context, value: Int): String {
@Composable
private fun LibraryColumnsPicker(
modifier: Modifier = Modifier,
portraitValue: Int,
onPortraitChange: (Int) -> Unit,
landscapeValue: Int,
onLandscapeChange: (Int) -> Unit,
) {
BoxWithConstraints(
modifier = modifier,
contentAlignment = Alignment.Center,
) {
Surface(
modifier = Modifier.size(maxWidth, maxHeight / 3),
shape = MaterialTheme.shapes.large,
color = MaterialTheme.colorScheme.primary.copy(alpha = 0.2f),
border = BorderStroke(1.dp, MaterialTheme.colorScheme.primary),
) {}
val size = DpSize(width = maxWidth / 2, height = 128.dp)
Row {
WheelPicker(
size = size,
count = 10,
startIndex = portraitValue,
onScrollFinished = {
onPortraitChange(it)
null
},
) { index, snappedIndex ->
ColumnPickerLabel(index = index, snappedIndex = snappedIndex)
}
WheelPicker(
size = size,
count = 10,
startIndex = landscapeValue,
onScrollFinished = {
onLandscapeChange(it)
null
},
) { index, snappedIndex ->
ColumnPickerLabel(index = index, snappedIndex = snappedIndex)
}
}
}
}
@Composable
private fun ColumnPickerLabel(
index: Int,
snappedIndex: Int,
) {
Text(
modifier = Modifier.alpha(
when (snappedIndex) {
index + 1 -> 0.2f
index -> 1f
index - 1 -> 0.2f
else -> 0.2f
},
),
text = getColumnValue(index),
style = MaterialTheme.typography.titleMedium,
maxLines = 1,
)
}
@Composable
@ReadOnlyComposable
private fun getColumnValue(value: Int): String {
return if (value == 0) {
context.getString(R.string.label_default)
stringResource(R.string.label_default)
} else {
value.toString()
}

View file

@ -1,40 +0,0 @@
package eu.kanade.tachiyomi.widget
import android.content.Context
import android.text.InputType
import android.util.AttributeSet
import android.widget.EditText
import android.widget.NumberPicker
import androidx.core.view.doOnLayout
import eu.kanade.tachiyomi.R
import eu.kanade.tachiyomi.util.view.findDescendant
class MinMaxNumberPicker @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
NumberPicker(context, attrs) {
override fun setDisplayedValues(displayedValues: Array<out String>?) {
super.setDisplayedValues(displayedValues)
// Disable keyboard input when a value that can't be auto-filled with number exists
val notNumberValue = displayedValues?.find { it.getOrNull(0)?.digitToIntOrNull() == null }
if (notNumberValue != null) {
descendantFocusability = FOCUS_BLOCK_DESCENDANTS
}
}
init {
if (attrs != null) {
val ta = context.obtainStyledAttributes(attrs, R.styleable.MinMaxNumberPicker, 0, 0)
try {
minValue = ta.getInt(R.styleable.MinMaxNumberPicker_min, 0)
maxValue = ta.getInt(R.styleable.MinMaxNumberPicker_max, 0)
} finally {
ta.recycle()
}
}
doOnLayout {
findDescendant<EditText>()?.setRawInputType(InputType.TYPE_CLASS_NUMBER)
}
}
}

View file

@ -1,11 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="MinMaxNumberPicker">
<attr name="min" format="integer"/>
<attr name="max" format="integer"/>
</declare-styleable>
<declare-styleable name="MaterialSpinnerView">
<attr name="title" format="reference|string"/>
<attr name="android:entries"/>

View file

@ -16,6 +16,9 @@ material3-core = { module = "androidx.compose.material3:material3" }
material3-adapter = "com.google.android.material:compose-theme-adapter-3:1.0.21"
material-icons = { module = "androidx.compose.material:material-icons-extended" }
# Here until M3's swipeable became public https://issuetracker.google.com/issues/234640556
material-core = { module = "androidx.compose.material:material" }
accompanist-webview = { module = "com.google.accompanist:accompanist-webview", version.ref = "accompanist" }
accompanist-swiperefresh = { module = "com.google.accompanist:accompanist-swiperefresh", version.ref = "accompanist" }
accompanist-flowlayout = { module = "com.google.accompanist:accompanist-flowlayout", version.ref = "accompanist" }

View file

@ -63,7 +63,6 @@ photoview = "com.github.chrisbanes:PhotoView:2.3.0"
directionalviewpager = "com.github.tachiyomiorg:DirectionalViewPager:1.0.0"
insetter = "dev.chrisbanes.insetter:insetter:0.6.1"
cascade = "me.saket.cascade:cascade-compose:2.0.0-beta1"
numberpicker = "com.chargemap.compose:numberpicker:1.0.3"
wheelpicker = "com.github.commandiron:WheelPickerCompose:1.0.11"
conductor-core = { module = "com.bluelinelabs:conductor", version.ref = "conductor_version" }