The user of our app should be able to adjust a floating point number. At the moment, I filled an ArrayAdapter with all possible values and attached it to a spinner.
This
In Kotlin, you can use this handy NumberPicker
extension dialog which scales your Double
values into a fitting Int
range and converts the Int
values back to Double
s before calling any of the callback. So it basicallly hides away the fact that NumberPicker
only supports Int
. It just feels like NumberPicker
would actually support Double
, try it out!
Here's the Fragment extension you need to copy & paste:
fun Fragment.showNumberPickerDialog(
title: String,
value: Double,
range: ClosedRange,
stepSize: Double,
formatToString: (Double) -> String,
valueChooseAction: (Double) -> Unit
) {
val numberPicker = NumberPicker(context).apply {
setFormatter { formatToString(it.toDouble() * stepSize) }
wrapSelectorWheel = false
minValue = (range.start / stepSize).toInt()
maxValue = (range.endInclusive / stepSize).toInt()
this.value = (value.toDouble() / stepSize).toInt()
// NOTE: workaround for a bug that rendered the selected value wrong until user scrolled, see also: https://stackoverflow.com/q/27343772/3451975
(NumberPicker::class.java.getDeclaredField("mInputText").apply { isAccessible = true }.get(this) as EditText).filters = emptyArray()
}
MaterialAlertDialogBuilder(context)
.setTitle(title)
.setView(numberPicker)
.setPositiveButton("OK") { _, _ -> valueChooseAction(numberPicker.value.toDouble() * stepSize) }
.setNeutralButton("Cancel") { _, _ -> /* do nothing, closes dialog automatically */ }
.show()
}
Now you can use it like this (in a Fragment
):
showNumberPickerDialog(
title = "Your Weight",
value = 75.0, // in kilograms
range = 10.0 .. 300.0,
stepSize = 0.1,
formatToString = { "$it kg" },
valueChooseAction = { saveNewWeight(it) }
)