Is there any way to specify the input method type for android.support.v7.preference.EditTextPreference
?
Now one can use Android-Support-Preference-V7-Fix library.
Fixed EditTextPreference
forwards the XML attributes (like inputType
) to the EditText
, just like the original preference did.
setOnBindEditTextListener
method which can be used to work around the issue. You can change the EditText input type from within the listener. See developer.android.com/reference/androidx/preference/… –
Hadsall If you don't want to use a third party library, it is possible to specify a layout to the EditTextPreference
<EditTextPreference android:defaultValue="0"
android:key="some_key"
android:title="Title"
android:dialogLayout="@layout/preference_edit_text"/>
Then in res/layout/preference_edit_text.xml
<android.support.constraint.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="wrap_content">
<EditText android:id="@android:id/edit"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inputType="number"
android:singleLine="true"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_marginStart="21dp"
android:layout_marginEnd="21dp"/>
</android.support.constraint.ConstraintLayout>
Please note that the edit text id must be : @android:id/edit
but then you are free to use whatever you want inside the android:inputType
field
I'm sure there's a better way to align the EditText rather than using 21dp
margins
but at least it works
Now one can use Android-Support-Preference-V7-Fix library.
Fixed EditTextPreference
forwards the XML attributes (like inputType
) to the EditText
, just like the original preference did.
setOnBindEditTextListener
method which can be used to work around the issue. You can change the EditText input type from within the listener. See developer.android.com/reference/androidx/preference/… –
Hadsall Here is my version of the answer from Cory Charlton, transfered to Jetpack preferences and written in Kotlin:
import android.content.Context
import android.content.SharedPreferences
import android.text.InputType
import android.util.AttributeSet
import androidx.preference.EditTextPreference
class EditIntegerPreference : EditTextPreference {
constructor(context: Context?) : super(context) {
setInputMethod()
}
constructor(context: Context?, attributeSet: AttributeSet?) : super(context, attributeSet) {
setInputMethod()
}
constructor(context: Context?, attributeSet: AttributeSet?, defStyle: Int) : super(
context,
attributeSet,
defStyle
) {
setInputMethod()
}
override fun getText(): String =
try {
java.lang.String.valueOf(sharedPreferences.getInt(key, 0))
} catch (e: Exception) {
"0"
}
override fun setText(text: String?) {
try {
if (text != null) {
sharedPreferences?.edit()?.putInt(key, text.toInt())?.apply()
summary = text
} else {
sharedPreferences?.remove(key)
summary = ""
}
} catch (e: Exception) {
sharedPreferences?.remove(key)
summary = ""
}
}
override fun onSetInitialValue(defaultValue: Any?) {
val defaultValueInt: Int =
when (defaultValue){
is Int -> defaultValue
is String -> try {defaultValue.toInt()} catch (ex: java.lang.Exception){0}
else -> 0
}
text = sharedPreferences.getInt(key, defaultValueInt).toString()
}
private fun setInputMethod() {
setOnBindEditTextListener {
it.inputType = InputType.TYPE_CLASS_NUMBER
}
}
fun SharedPreferences.remove(key: String) = edit().remove(key).apply()
}
PreferenceDatastore
is used? How can we then bind the above to a custom DataStore
? –
Oracular Edit: The previous answers below were built on the stock android.preference.EditTextPreference
and unfortunately don't work for the android.support.v7.preference.EditTextPreference
.
In the android.preference.EditTextPreference
the EditText
control is created programmatically and the AttributeSet
from the Preference
is passed to it.
android.preference.EditTextPreference
Source:
public EditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
mEditText = new EditText(context, attrs);
// Give it an ID so it can be saved/restored
mEditText.setId(com.android.internal.R.id.edit);
/*
* The preference framework and view framework both have an 'enabled'
* attribute. Most likely, the 'enabled' specified in this XML is for
* the preference framework, but it was also given to the view framework.
* We reset the enabled state.
*/
mEditText.setEnabled(true);
}
White allows us to set the inputType
on the Preference
itself and have it pass through to the EditText
. Unfortunately the android.support.v7.preference.EditTextPreference
appears to create the EditText
in the Layout
See this issue for ideas on working around this:
Just wanted to let you know that subclassing EditTextPreferenceDialogFragment and overriding onAddEditTextToDialogView as well as overriding PreferenceFragmentCompat#onDisplayPreferenceDialog to show that subclass as needed seems to be working fine, thanks for the help.
Create your own class that extends the EditTextPreference
and set it there.
Here's my EditIntegerPreference
class:
public class EditIntegerPreference extends EditTextPreference {
public EditIntegerPreference(Context context) {
super(context);
}
public EditIntegerPreference(Context context, AttributeSet attributeSet) {
super(context, attributeSet);
}
public EditIntegerPreference(Context context, AttributeSet attributeSet, int defStyle) {
super(context, attributeSet, defStyle);
getEditText().setInputType(InputType.TYPE_CLASS_NUMBER);
getEditText().setSelectAllOnFocus(true);
}
@Override
public String getText() {
try {
return String.valueOf(getSharedPreferences().getInt(getKey(), 0));
} catch (Exception e) {
return getSharedPreferences().getString(getKey(), "0");
}
}
@Override
public void setText(String text) {
try {
if (getSharedPreferences() != null) {
getSharedPreferences().edit().putInt(getKey(), Integer.parseInt(text)).commit();
}
} catch (Exception e) {
// TODO: This catch stinks!
}
}
@Override
protected void onSetInitialValue(boolean restoreValue, Object defaultValue) {
getEditText().setInputType(InputType.TYPE_CLASS_NUMBER);
getEditText().setSelectAllOnFocus(true);
if (restoreValue) {
getEditText().setText(getText());
} else {
super.onSetInitialValue(restoreValue, defaultValue != null ? defaultValue : "");
}
}
}
Note that it is possible to add the inputType
attribute to the the EditTextPreference
android:inputType="number"
The reason I didn't go this route is that I wanted my preference to get stored as an Integer
and not a String
android.support.v7.preference.EditTextPreference
doesn't contain getEditText()
method. –
Amygdalate android.support.v7.preference.EditTextPreference
? I ask because android.preference.EditTextPreference
has existed since API level 1. –
Soprano PreferenceFragmentCompat
. –
Amygdalate PreferenceFragmentCompat
yet. Not sure why the support implementation is a regression from the stock Preference
. I'll see if I can find anything else. –
Soprano Workaround for Kotlin + DataStore + androidx.Preference
Disclaimer!
Probably this isn't the way to do it!
Ideally one should only:
- set the input to int
- override in a
DataStore
class:putInt
/getInt
Extension Function
In my case I had a PreferenceFragmentCompat
, so:
fun PreferenceFragmentCompat.setNumericInput(
@StringRes prefRes: Int, initialValue: String) {
val preference = findPreference(getString(prefRes)) as EditTextPreference?
preference?.setOnBindEditTextListener { editText ->
editText.inputType = InputType.TYPE_CLASS_NUMBER or
InputType.TYPE_NUMBER_FLAG_SIGNED
// set the initial value: I read it from the DataStore and then
// pass it as the 2nd argument to setNumericInput.
// BTW, I do store stringPreferenceKeys, as it's the putString method
// that get's triggered
if (editText.text.isEmpty()) editText.setText(initialValue)
editText.setSelection(editText.text.length) // put cursor at the end
}
// to use it in the summary do something like:
preference?.setOnPreferenceChangeListener { it, newValue ->
it.summary = "updated: $newValue"
true
}
}
Also, in my Activity that extends BaseSettingsActivity
I
replace the management from SharedPreferences
using:
preferenceManager.preferenceDataStore = dataStoreCvLogger
© 2022 - 2024 — McMap. All rights reserved.