Skip to content

Commit 67a3497

Browse files
committed
Add VersatileTextPreference
At the time being, it serves two purposes: * It supports changing input type via android:inputType XML attribute, which can help the keyboard app with choosing a more suitable keyboard layout. * If continuousValidator is set, it is used to prevent the user from entering invalid data. On each text change, the validator is run; if it throws, the Ok button gets disabled. It was designed as a drop-in replacement of EditTextPreference with the extra functionality disabled by default. Additional functionality can be added as needed.
1 parent 5e5a913 commit 67a3497

File tree

1 file changed

+85
-0
lines changed

1 file changed

+85
-0
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
/*
2+
* This program is free software; you can redistribute it and/or modify it under
3+
* the terms of the GNU General Public License as published by the Free Software
4+
* Foundation; either version 3 of the License, or (at your option) any later
5+
* version.
6+
*
7+
* This program is distributed in the hope that it will be useful, but WITHOUT ANY
8+
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
9+
* PARTICULAR PURPOSE. See the GNU General Public License for more details.
10+
*
11+
* You should have received a copy of the GNU General Public License along with
12+
* this program. If not, see <http://www.gnu.org/licenses/>.
13+
*/
14+
15+
package com.ichi2.anki.preferences
16+
17+
import android.content.Context
18+
import android.content.DialogInterface
19+
import android.util.AttributeSet
20+
import android.view.View
21+
import android.widget.EditText
22+
import androidx.appcompat.app.AlertDialog
23+
import androidx.appcompat.widget.AppCompatEditText
24+
import androidx.core.widget.addTextChangedListener
25+
import androidx.preference.EditTextPreference
26+
import androidx.preference.EditTextPreferenceDialogFragmentCompat
27+
import kotlin.jvm.Throws
28+
29+
/**
30+
* A drop-in alternative to [EditTextPreference] with some extra functionality.
31+
*
32+
* * It supports changing input type via `android:inputType` XML attribute,
33+
* which can help the keyboard app with choosing a more suitable keyboard layout.
34+
* For the list of available input types, see [TextView.getInputType].
35+
*
36+
* * If [continuousValidator] is set, the dialog uses it to prevent user
37+
* from entering invalid data. On each text change, the validator is run;
38+
* if it throws, the Ok button gets disabled.
39+
*/
40+
open class VersatileTextPreference(context: Context, attrs: AttributeSet?) :
41+
EditTextPreference(context, attrs), DialogFragmentProvider {
42+
43+
fun interface Validator {
44+
@Throws(Exception::class) fun validate(value: String)
45+
}
46+
47+
val referenceEditText = AppCompatEditText(context, attrs)
48+
49+
var continuousValidator: Validator? = null
50+
51+
override fun makeDialogFragment() = VersatileTextPreferenceDialogFragment()
52+
}
53+
54+
open class VersatileTextPreferenceDialogFragment : EditTextPreferenceDialogFragmentCompat() {
55+
56+
private val versatileTextPreference get() = preference as VersatileTextPreference
57+
58+
protected lateinit var editText: EditText
59+
60+
// This changes input type first, as it resets the cursor,
61+
// And only then calls super, which sets up text and moves the cursor to end.
62+
//
63+
// Positive button isn't present in a dialog until it is shown, which happens around onStart;
64+
// for simplicity, obtain it in the listener itself.
65+
override fun onBindDialogView(contentView: View) {
66+
editText = contentView.findViewById(android.R.id.edit)!!
67+
editText.inputType = versatileTextPreference.referenceEditText.inputType
68+
69+
super.onBindDialogView(contentView)
70+
71+
versatileTextPreference.continuousValidator?.let { validator ->
72+
editText.addTextChangedListener(afterTextChanged = {
73+
val alertDialog = dialog as AlertDialog
74+
val positiveButton = alertDialog.getButton(DialogInterface.BUTTON_POSITIVE)
75+
76+
positiveButton?.isEnabled = try {
77+
validator.validate(editText.text.toString())
78+
true
79+
} catch (e: Exception) {
80+
false
81+
}
82+
})
83+
}
84+
}
85+
}

0 commit comments

Comments
 (0)