Skip to content

Commit

Permalink
Merge pull request iSoron#1082 from hiqua/improve_number_picker
Browse files Browse the repository at this point in the history
Make numpad work better in number picker dialog
  • Loading branch information
iSoron authored Sep 11, 2021
2 parents fc14786 + 1d37ce5 commit 0e988e7
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,11 @@

package org.isoron.uhabits.activities.common.dialogs

import android.annotation.SuppressLint
import android.content.Context
import android.content.DialogInterface
import android.text.InputFilter
import android.text.Spanned
import android.view.LayoutInflater
import android.view.WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE
import android.view.inputmethod.EditorInfo
Expand All @@ -33,25 +35,35 @@ import org.isoron.uhabits.R
import org.isoron.uhabits.core.ui.screens.habits.list.ListHabitsBehavior
import org.isoron.uhabits.inject.ActivityContext
import org.isoron.uhabits.utils.InterfaceUtils
import java.text.DecimalFormatSymbols
import javax.inject.Inject
import kotlin.math.roundToLong

class NumberPickerFactory
@Inject constructor(
@ActivityContext private val context: Context
) {

fun create(
value: Double,
unit: String,
callback: ListHabitsBehavior.NumberPickerCallback
): AlertDialog {

val inflater = LayoutInflater.from(context)
val view = inflater.inflate(R.layout.number_picker_dialog, null)

val picker = view.findViewById<NumberPicker>(R.id.picker)
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()

Expand All @@ -61,19 +73,16 @@ class NumberPickerFactory
picker.wrapSelectorWheel = false

picker2.minValue = 0
picker2.maxValue = 19
picker2.setFormatter { v -> String.format("%02d", 5 * v) }
picker2.value = intValue % 100 / 5
refreshInitialValue(picker2)

tvUnit.text = unit
picker2.maxValue = 99
picker2.setFormatter { v -> String.format("%02d", v) }
picker2.value = intValue % 100

val dialog = AlertDialog.Builder(context)
.setView(view)
.setTitle(R.string.change_value)
.setPositiveButton(android.R.string.ok) { _, _ ->
picker.clearFocus()
val v = picker.value + 0.05 * picker2.value
val v = picker.value + 0.01 * picker2.value
callback.onNumberPicked(v)
}
.setOnDismissListener {
Expand All @@ -89,20 +98,50 @@ class NumberPickerFactory
InterfaceUtils.setupEditorAction(
picker
) { _, 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()
}
false
}

return dialog
}

private fun refreshInitialValue(picker: NumberPicker) {
// Workaround for Android bug:
// https://code.google.com/p/android/issues/detail?id=35482
@SuppressLint("DiscouragedPrivateApi")
private fun getNumberPickerInputText(picker: NumberPicker): EditText {
val f = NumberPicker::class.java.getDeclaredField("mInputText")
f.isAccessible = true
val inputText = f.get(picker) as EditText
inputText.filters = arrayOfNulls<InputFilter>(0)
return f.get(picker) as EditText
}
}

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
}
}
3 changes: 1 addition & 2 deletions uhabits-android/src/main/res/layout/number_picker_dialog.xml
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,13 @@
android:id="@+id/tvSeparator"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="."/>
/>

<NumberPicker
android:id="@+id/picker2"
android:layout_gravity="center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:descendantFocusability="blocksDescendants"
/>

<TextView
Expand Down

0 comments on commit 0e988e7

Please sign in to comment.