From 79b2428592baffedfa4848120b8e8b5c8e40fac5 Mon Sep 17 00:00:00 2001 From: Maxr1998 Date: Thu, 10 Dec 2020 23:21:20 +0100 Subject: [PATCH] Implement EditTextPreference --- .../helpers/PreferencesDsl.kt | 4 + .../preferences/EditTextPreference.kt | 97 +++++++++++++++++++ .../modernpreferences/example/Common.kt | 4 + 3 files changed, 105 insertions(+) create mode 100644 library/src/main/java/de/Maxr1998/modernpreferences/preferences/EditTextPreference.kt diff --git a/library/src/main/java/de/Maxr1998/modernpreferences/helpers/PreferencesDsl.kt b/library/src/main/java/de/Maxr1998/modernpreferences/helpers/PreferencesDsl.kt index ef652bbd..dcab60f9 100644 --- a/library/src/main/java/de/Maxr1998/modernpreferences/helpers/PreferencesDsl.kt +++ b/library/src/main/java/de/Maxr1998/modernpreferences/helpers/PreferencesDsl.kt @@ -84,6 +84,10 @@ inline fun PreferenceScreen.Appendable.multiChoice(key: String, items: List Unit): EditTextPreference { + return EditTextPreference(key).apply(block).also(::addPreferenceItem) +} + inline fun PreferenceScreen.Appendable.custom(key: String, block: T.() -> Unit): T { return T::class.java.getConstructor(String::class.java).newInstance(key).apply(block).also(::addPreferenceItem) } diff --git a/library/src/main/java/de/Maxr1998/modernpreferences/preferences/EditTextPreference.kt b/library/src/main/java/de/Maxr1998/modernpreferences/preferences/EditTextPreference.kt new file mode 100644 index 00000000..3feb97f2 --- /dev/null +++ b/library/src/main/java/de/Maxr1998/modernpreferences/preferences/EditTextPreference.kt @@ -0,0 +1,97 @@ +package de.Maxr1998.modernpreferences.preferences + +import android.app.Dialog +import android.content.Context +import android.text.InputType +import android.view.ViewGroup +import android.view.ViewGroup.LayoutParams.MATCH_PARENT +import android.view.ViewGroup.LayoutParams.WRAP_CONTENT +import android.widget.FrameLayout +import androidx.annotation.StringRes +import androidx.appcompat.app.AlertDialog +import androidx.appcompat.widget.AppCompatEditText + +class EditTextPreference(key: String) : DialogPreference(key) { + + var currentInput: CharSequence? = null + private set + + /** + * The [InputType] applied to the contained [EditText][AppCompatEditText] + */ + var textInputType: Int = InputType.TYPE_NULL + + @StringRes + var textInputHintRes: Int = -1 + var textInputHint: CharSequence? = null + + var textChangeListener: OnTextChangeListener? = null + + /** + * Allows to override the summary, providing the current input value when called. + * + * Summary falls back to [summary] or [summaryRes] when null is returned. + */ + var summaryProvider: (CharSequence?) -> CharSequence? = { null } + + override fun onAttach() { + super.onAttach() + if (currentInput == null) + currentInput = getString() + } + + override fun createDialog(context: Context): Dialog = AlertDialog.Builder(context).apply { + if (titleRes != -1) setTitle(titleRes) else setTitle(title) + val editText = AppCompatEditText(context).apply { + if (textInputType != InputType.TYPE_NULL) { + inputType = textInputType + } + when { + textInputHintRes != -1 -> setHint(textInputHintRes) + textInputHint != null -> hint = textInputHint + } + setText(currentInput) + } + setView(FrameLayout(context).apply { + val layoutParams = ViewGroup.MarginLayoutParams(MATCH_PARENT, WRAP_CONTENT).apply { + val tenDp = (10 * context.resources.displayMetrics.density).toInt() + marginStart = 2 * tenDp + marginEnd = 2 * tenDp + topMargin = tenDp + } + addView(editText, layoutParams) + }) + setCancelable(false) + setPositiveButton(android.R.string.ok) { _, _ -> + editText.text?.let(::persist) + requestRebind() + } + setNegativeButton(android.R.string.cancel) { _, _ -> + editText.setText(currentInput) + } + }.create() + + private fun persist(input: CharSequence) { + if (textChangeListener?.onTextChange(this, input) != false) { + currentInput = input + commitString(input.toString()) + } + } + + override fun resolveSummary(context: Context): CharSequence? { + return summaryProvider(currentInput) ?: super.resolveSummary(context) + } + + fun interface OnTextChangeListener { + /** + * Notified when the value of the connected [EditTextPreference] changes, + * meaning after the user closes the dialog by pressing "ok". + * This is called before the change gets persisted and can be prevented by returning false. + * + * @param text the new value + * + * @return true to commit the new value to [SharedPreferences][android.content.SharedPreferences] + */ + fun onTextChange(preference: EditTextPreference, text: CharSequence): Boolean + } +} \ No newline at end of file diff --git a/testapp/src/main/java/de/Maxr1998/modernpreferences/example/Common.kt b/testapp/src/main/java/de/Maxr1998/modernpreferences/example/Common.kt index 939faf01..39795516 100644 --- a/testapp/src/main/java/de/Maxr1998/modernpreferences/example/Common.kt +++ b/testapp/src/main/java/de/Maxr1998/modernpreferences/example/Common.kt @@ -130,6 +130,10 @@ object Common { multiChoice("multi-choice-dialog", selectableItems) { title = "Multi choice selection dialog" } + editText("edit-text") { + title = "Text input" + textInputHint = "Enter whatever you want!" + } expandText("expand-text") { title = "Expandable text" text = "This is an example implementation of ModernAndroidPreferences, check out " +