Merge pull request #1082 from hiqua/improve_number_picker

Make numpad work better in number picker dialog
pull/1107/head
Alinson S. Xavier 4 years ago committed by GitHub
commit 0e988e746c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -19,9 +19,11 @@
package org.isoron.uhabits.activities.common.dialogs package org.isoron.uhabits.activities.common.dialogs
import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.DialogInterface import android.content.DialogInterface
import android.text.InputFilter import android.text.InputFilter
import android.text.Spanned
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
@ -33,6 +35,7 @@ import org.isoron.uhabits.R
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
import org.isoron.uhabits.inject.ActivityContext import org.isoron.uhabits.inject.ActivityContext
import org.isoron.uhabits.utils.InterfaceUtils import org.isoron.uhabits.utils.InterfaceUtils
import java.text.DecimalFormatSymbols
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.roundToLong import kotlin.math.roundToLong
@ -40,18 +43,27 @@ class NumberPickerFactory
@Inject constructor( @Inject constructor(
@ActivityContext private val context: Context @ActivityContext private val context: Context
) { ) {
fun create( fun create(
value: Double, value: Double,
unit: String, unit: String,
callback: ListHabitsBehavior.NumberPickerCallback callback: ListHabitsBehavior.NumberPickerCallback
): AlertDialog { ): AlertDialog {
val inflater = LayoutInflater.from(context) val inflater = LayoutInflater.from(context)
val view = inflater.inflate(R.layout.number_picker_dialog, null) val view = inflater.inflate(R.layout.number_picker_dialog, null)
val picker = view.findViewById<NumberPicker>(R.id.picker) val picker = view.findViewById<NumberPicker>(R.id.picker)
val picker2 = view.findViewById<NumberPicker>(R.id.picker2) val picker2 = view.findViewById<NumberPicker>(R.id.picker2)
val tvUnit = view.findViewById<TextView>(R.id.tvUnit)
val watcherFilter: InputFilter = SeparatorWatcherInputFilter(picker2)
val numberPickerInputText = getNumberPickerInputText(picker)
// watch the unfiltered input before the filters remove a possible separator from it
numberPickerInputText.filters = arrayOf(watcherFilter).plus(numberPickerInputText.filters)
view.findViewById<TextView>(R.id.tvUnit).text = unit
view.findViewById<TextView>(R.id.tvSeparator).text =
DecimalFormatSymbols.getInstance().decimalSeparator.toString()
val intValue = (value * 100).roundToLong().toInt() val intValue = (value * 100).roundToLong().toInt()
@ -61,19 +73,16 @@ class NumberPickerFactory
picker.wrapSelectorWheel = false picker.wrapSelectorWheel = false
picker2.minValue = 0 picker2.minValue = 0
picker2.maxValue = 19 picker2.maxValue = 99
picker2.setFormatter { v -> String.format("%02d", 5 * v) } picker2.setFormatter { v -> String.format("%02d", v) }
picker2.value = intValue % 100 / 5 picker2.value = intValue % 100
refreshInitialValue(picker2)
tvUnit.text = unit
val dialog = AlertDialog.Builder(context) val dialog = AlertDialog.Builder(context)
.setView(view) .setView(view)
.setTitle(R.string.change_value) .setTitle(R.string.change_value)
.setPositiveButton(android.R.string.ok) { _, _ -> .setPositiveButton(android.R.string.ok) { _, _ ->
picker.clearFocus() picker.clearFocus()
val v = picker.value + 0.05 * picker2.value val v = picker.value + 0.01 * picker2.value
callback.onNumberPicked(v) callback.onNumberPicked(v)
} }
.setOnDismissListener { .setOnDismissListener {
@ -89,20 +98,50 @@ class NumberPickerFactory
InterfaceUtils.setupEditorAction( InterfaceUtils.setupEditorAction(
picker picker
) { _, actionId, _ -> ) { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) if (actionId == EditorInfo.IME_ACTION_DONE) {
dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick()
}
false
}
InterfaceUtils.setupEditorAction(
picker2
) { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_DONE) {
dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick() dialog.getButton(DialogInterface.BUTTON_POSITIVE).performClick()
}
false false
} }
return dialog return dialog
} }
private fun refreshInitialValue(picker: NumberPicker) { @SuppressLint("DiscouragedPrivateApi")
// Workaround for Android bug: private fun getNumberPickerInputText(picker: NumberPicker): EditText {
// https://code.google.com/p/android/issues/detail?id=35482
val f = NumberPicker::class.java.getDeclaredField("mInputText") val f = NumberPicker::class.java.getDeclaredField("mInputText")
f.isAccessible = true f.isAccessible = true
val inputText = f.get(picker) as EditText return f.get(picker) as EditText
inputText.filters = arrayOfNulls<InputFilter>(0) }
}
class SeparatorWatcherInputFilter(private val nextPicker: NumberPicker) : InputFilter {
override fun filter(
source: CharSequence?,
start: Int,
end: Int,
dest: Spanned?,
dstart: Int,
dend: Int
): CharSequence {
if (source == null || source.isEmpty()) {
return ""
}
for (c in source) {
if (c == DecimalFormatSymbols.getInstance().decimalSeparator || c == '.' || c == ',') {
nextPicker.performLongClick()
break
}
}
return source
} }
} }

@ -34,14 +34,13 @@
android:id="@+id/tvSeparator" android:id="@+id/tvSeparator"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="."/> />
<NumberPicker <NumberPicker
android:id="@+id/picker2" android:id="@+id/picker2"
android:layout_gravity="center" android:layout_gravity="center"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
/> />
<TextView <TextView

Loading…
Cancel
Save