Просмотр исходного кода

现在数值选择可以直接输入

HapeLee 1 год назад
Родитель
Сommit
2c1ca1b1e8

+ 59 - 20
app/src/main/java/io/legato/kazusa/ui/widget/number/NumberPickerDialog.kt

@@ -1,8 +1,15 @@
 package io.legato.kazusa.ui.widget.number
 
+import android.app.AlertDialog
 import android.content.Context
+import android.view.View
+import android.widget.LinearLayout
 import android.widget.NumberPicker
+import android.widget.TextView
+import com.google.android.material.button.MaterialButton
 import com.google.android.material.dialog.MaterialAlertDialogBuilder
+import com.google.android.material.textfield.TextInputEditText
+import com.google.android.material.textfield.TextInputLayout
 import io.legato.kazusa.R
 import io.legato.kazusa.utils.hideSoftInput
 
@@ -10,9 +17,13 @@ import io.legato.kazusa.utils.hideSoftInput
 class NumberPickerDialog(context: Context) {
     private val builder = MaterialAlertDialogBuilder(context)
     private var numberPicker: NumberPicker? = null
+    private var editText: TextInputEditText? = null
+    private var inputLayout: TextInputLayout? = null
+    private var tvRange: TextView? = null
     private var maxValue: Int? = null
     private var minValue: Int? = null
     private var value: Int? = null
+    private var useInputMode = false
 
     init {
         builder.setView(R.layout.dialog_number_picker)
@@ -40,36 +51,64 @@ class NumberPickerDialog(context: Context) {
 
     fun setCustomButton(textId: Int, listener: (() -> Unit)?): NumberPickerDialog {
         builder.setNeutralButton(textId) { _, _ ->
-            numberPicker?.let {
-                it.clearFocus()
-                it.hideSoftInput()
-                listener?.invoke()
-            }
+            numberPicker?.clearFocus()
+            listener?.invoke()
         }
         return this
     }
 
     fun show(callBack: ((value: Int) -> Unit)?) {
-        builder.setPositiveButton(R.string.ok) { _, _ ->
-            numberPicker?.let {
-                it.clearFocus()
-                it.hideSoftInput()
-                callBack?.invoke(it.value)
-            }
-        }
+        builder.setPositiveButton(R.string.ok, null)
         builder.setNegativeButton(R.string.cancel, null)
         val dialog = builder.show()
+
         numberPicker = dialog.findViewById(R.id.number_picker)
+        inputLayout = dialog.findViewById(R.id.til_input)
+        editText = dialog.findViewById(R.id.et_input)
+        tvRange = dialog.findViewById(R.id.tv_range)
+        val btnSwitch = dialog.findViewById<MaterialButton>(R.id.btn_switch_input)
+
         numberPicker?.let { np ->
-            minValue?.let {
-                np.minValue = it
-            }
-            maxValue?.let {
-                np.maxValue = it
+            minValue?.let { np.minValue = it }
+            maxValue?.let { np.maxValue = it }
+            value?.let { np.value = it }
+        }
+        tvRange?.text = "输入范围: ${numberPicker?.minValue} - ${numberPicker?.maxValue}"
+
+        btnSwitch?.setOnClickListener {
+            useInputMode = !useInputMode
+            if (useInputMode) {
+                numberPicker?.visibility = View.GONE
+                inputLayout?.visibility = View.VISIBLE
+                tvRange?.visibility = View.VISIBLE
+                editText?.setText(numberPicker?.value?.toString() ?: value?.toString())
+            } else {
+                numberPicker?.visibility = View.VISIBLE
+                inputLayout?.visibility = View.GONE
+                tvRange?.visibility = View.GONE
+                inputLayout?.error = null
             }
-            value?.let {
-                np.value = it
+        }
+
+        dialog.getButton(AlertDialog.BUTTON_POSITIVE)?.setOnClickListener {
+            if (useInputMode) {
+                val num = editText?.text?.toString()?.toIntOrNull()
+                val min = minValue ?: numberPicker?.minValue ?: Int.MIN_VALUE
+                val max = maxValue ?: numberPicker?.maxValue ?: Int.MAX_VALUE
+                if (num == null || num !in min..max) {
+                    inputLayout?.error = "请输入 $min - $max 范围内的数字"
+                } else {
+                    inputLayout?.error = null
+                    callBack?.invoke(num)
+                    dialog.dismiss()
+                }
+            } else {
+                numberPicker?.let {
+                    it.clearFocus()
+                    callBack?.invoke(it.value)
+                    dialog.dismiss()
+                }
             }
         }
     }
-}
+}

+ 47 - 5
app/src/main/res/layout/dialog_number_picker.xml

@@ -1,13 +1,55 @@
 <?xml version="1.0" encoding="utf-8"?>
-<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<androidx.constraintlayout.widget.ConstraintLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
-    android:layout_height="match_parent">
+    android:layout_height="match_parent"
+    android:padding="24dp"
+    android:gravity="center">
 
     <NumberPicker
         android:id="@+id/number_picker"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_gravity="center"
-        android:scrollbars="none" />
+        android:scrollbars="none"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toEndOf="@id/btn_switch_input"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"/>
 
-</FrameLayout>
+    <TextView
+        android:id="@+id/tv_range"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:visibility="gone"
+        app:layout_constraintBottom_toTopOf="@id/til_input"
+        app:layout_constraintStart_toStartOf="@id/til_input"/>
+
+    <com.google.android.material.textfield.TextInputLayout
+        android:id="@+id/til_input"
+        android:layout_width="0dp"
+        android:layout_height="wrap_content"
+        android:visibility="gone"
+        android:layout_marginEnd="16dp"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintEnd_toStartOf="@id/btn_switch_input"
+        app:layout_constraintTop_toBottomOf="@id/btn_switch_input"
+        app:layout_constraintBottom_toTopOf="@id/btn_switch_input">
+
+        <com.google.android.material.textfield.TextInputEditText
+            android:id="@+id/et_input"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:inputType="number" />
+    </com.google.android.material.textfield.TextInputLayout>
+
+    <com.google.android.material.button.MaterialButton
+        android:id="@+id/btn_switch_input"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        app:icon="@drawable/ic_swap_horiz"
+        style="@style/Widget.Material3Expressive.Button.IconButton.Outlined"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintTop_toTopOf="parent"
+        app:layout_constraintBottom_toBottomOf="parent"/>
+</androidx.constraintlayout.widget.ConstraintLayout>