1+ package de.Maxr1998.modernpreferences.preferences
2+
3+ import android.app.Dialog
4+ import android.content.Context
5+ import android.text.InputType
6+ import android.view.ViewGroup
7+ import android.view.ViewGroup.LayoutParams.MATCH_PARENT
8+ import android.view.ViewGroup.LayoutParams.WRAP_CONTENT
9+ import android.widget.FrameLayout
10+ import androidx.annotation.StringRes
11+ import androidx.appcompat.app.AlertDialog
12+ import androidx.appcompat.widget.AppCompatEditText
13+
14+ class EditTextPreference (key : String ) : DialogPreference(key) {
15+
16+ var currentInput: CharSequence? = null
17+ private set
18+
19+ /* *
20+ * The [InputType] applied to the contained [EditText][AppCompatEditText]
21+ */
22+ var textInputType: Int = InputType .TYPE_NULL
23+
24+ @StringRes
25+ var textInputHintRes: Int = - 1
26+ var textInputHint: CharSequence? = null
27+
28+ var textChangeListener: OnTextChangeListener ? = null
29+
30+ /* *
31+ * Allows to override the summary, providing the current input value when called.
32+ *
33+ * Summary falls back to [summary] or [summaryRes] when null is returned.
34+ */
35+ var summaryProvider: (CharSequence? ) -> CharSequence? = { null }
36+
37+ override fun onAttach () {
38+ super .onAttach()
39+ if (currentInput == null )
40+ currentInput = getString()
41+ }
42+
43+ override fun createDialog (context : Context ): Dialog = AlertDialog .Builder (context).apply {
44+ if (titleRes != - 1 ) setTitle(titleRes) else setTitle(title)
45+ val editText = AppCompatEditText (context).apply {
46+ if (textInputType != InputType .TYPE_NULL ) {
47+ inputType = textInputType
48+ }
49+ when {
50+ textInputHintRes != - 1 -> setHint(textInputHintRes)
51+ textInputHint != null -> hint = textInputHint
52+ }
53+ setText(currentInput)
54+ }
55+ setView(FrameLayout (context).apply {
56+ val layoutParams = ViewGroup .MarginLayoutParams (MATCH_PARENT , WRAP_CONTENT ).apply {
57+ val tenDp = (10 * context.resources.displayMetrics.density).toInt()
58+ marginStart = 2 * tenDp
59+ marginEnd = 2 * tenDp
60+ topMargin = tenDp
61+ }
62+ addView(editText, layoutParams)
63+ })
64+ setCancelable(false )
65+ setPositiveButton(android.R .string.ok) { _, _ ->
66+ editText.text?.let (::persist)
67+ requestRebind()
68+ }
69+ setNegativeButton(android.R .string.cancel) { _, _ ->
70+ editText.setText(currentInput)
71+ }
72+ }.create()
73+
74+ private fun persist (input : CharSequence ) {
75+ if (textChangeListener?.onTextChange(this , input) != false ) {
76+ currentInput = input
77+ commitString(input.toString())
78+ }
79+ }
80+
81+ override fun resolveSummary (context : Context ): CharSequence? {
82+ return summaryProvider(currentInput) ? : super .resolveSummary(context)
83+ }
84+
85+ fun interface OnTextChangeListener {
86+ /* *
87+ * Notified when the value of the connected [EditTextPreference] changes,
88+ * meaning after the user closes the dialog by pressing "ok".
89+ * This is called before the change gets persisted and can be prevented by returning false.
90+ *
91+ * @param text the new value
92+ *
93+ * @return true to commit the new value to [SharedPreferences][android.content.SharedPreferences]
94+ */
95+ fun onTextChange (preference : EditTextPreference , text : CharSequence ): Boolean
96+ }
97+ }
0 commit comments