EditTextPreference - only numeric value inputType - isn't working
Asked Answered
F

11

10
<android.support.v7.preference.EditTextPreference
            android:key="prefTest"
            android:title="test number input"
            android:inputType="numberDecimal|numberSigned"
            android:defaultValue="800"/>

It still shows regular keyboard and allows me to type any character

Is there something wrong with android.support.v7?

Fife answered 15/3, 2017 at 8:45 Comment(6)
Try android:inputType="number"Ellerey
@Ellerey didn't change anythingFife
@JohnJoe it didn't change anythingFife
downvoted for nothing..Fife
Please star this issue. The problem is occurring even with implementation "androidx.preference:preference:1.1.0"Extravascular
A current official guide for this is: developer.android.com/guide/topics/ui/settings/…Sheared
D
8
android:digits="0123456789"

use this in edittext as it accepts only defined numbers. if its not working then use Android-Support-Preference-V7-Fix library.

Fixed EditTextPreference forwards the XML attributes (like inputType) to the EditText, just like the original preference did.

Doorkeeper answered 15/3, 2017 at 9:1 Comment(5)
didn't help, support v7 preference is really bad I guessFife
then you should go with second method as i suggested in my comment.Doorkeeper
fix library solved the problem, omg google (developers of official support libraries) sucksFife
androidx ignores thisVagabond
Still the same issue in 2021 with AndroidX... I fixed it by copying "EditTextPreference.java" class from the specified link github.com/Gericop/Android-Support-Preference-V7-FixPonzo
J
10

The Customize your settings section in the developer guide for settings recommends that you set the input type programmatically by using an OnBindEditTextListener as follows:

public class SettingsFragment extends PreferenceFragmentCompat {
    @Override
    public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
        setPreferencesFromResource(R.xml.settings_screen, rootKey);

        EditTextPreference weeklyGoalPref = findPreference("weekly_goal");
        if (weeklyGoalPref != null) {
            weeklyGoalPref.setOnBindEditTextListener(new EditTextPreference.OnBindEditTextListener() {
                @Override
                public void onBindEditText(@NonNull EditText editText) {
                    editText.setInputType(InputType.TYPE_CLASS_NUMBER);
                }
            });
        }
    }
}

I tried defining the input type as "number" in xml and still got the normal keyboard with letters. This approach worked for me.

Judaea answered 30/3, 2020 at 23:36 Comment(2)
Doesn't work for me. I use androidx and leanback libraries. Using EditTextPreference inside LeanbackSettingsFragmentCompatKor
We still can parse the same XML to extract the attributes and set the input type accordingly, see https://mcmap.net/q/376320/-edittextpreference-only-numeric-value-inputtype-isn-39-t-workingMendel
D
8
android:digits="0123456789"

use this in edittext as it accepts only defined numbers. if its not working then use Android-Support-Preference-V7-Fix library.

Fixed EditTextPreference forwards the XML attributes (like inputType) to the EditText, just like the original preference did.

Doorkeeper answered 15/3, 2017 at 9:1 Comment(5)
didn't help, support v7 preference is really bad I guessFife
then you should go with second method as i suggested in my comment.Doorkeeper
fix library solved the problem, omg google (developers of official support libraries) sucksFife
androidx ignores thisVagabond
Still the same issue in 2021 with AndroidX... I fixed it by copying "EditTextPreference.java" class from the specified link github.com/Gericop/Android-Support-Preference-V7-FixPonzo
D
2

I agree that original support preferences has some issues, but for resolving this issue we just need add custom layout and specify EditText with android:inputType="number"

<android.support.v7.preference.EditTextPreference
            android:dialogLayout="@layout/preference_dialog_edittext_custom"

So that you may copy original preference_dialog_layout.xml file and edit it.

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:layout_marginTop="48dp"
    android:layout_marginBottom="48dp"
    android:overScrollMode="ifContentScrolls">

  <LinearLayout
      android:layout_width="match_parent"
      android:layout_height="wrap_content"
      android:layout_marginStart="24dp"
      android:layout_marginEnd="24dp"
      android:orientation="vertical">

    <TextView android:id="@android:id/message"
        style="?android:attr/textAppearanceSmall"
        android:layout_marginBottom="48dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:textColor="?android:attr/textColorSecondary" />

    <EditText
        android:id="@android:id/edit"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:inputType="number"
        android:layout_marginStart="-4dp"
        android:layout_marginEnd="-4dp" />

  </LinearLayout>

</ScrollView>
Dissepiment answered 1/12, 2018 at 14:43 Comment(0)
J
2

android.support.v7.preference.EditTextPreference doesn't contain getEditText() method.

But we can extends android.support.v7.preference.EditTextPreferenceDialogFragmentCompat to set inputType.

public class EditTextPreferenceDialogFragmentCompat extends android.support.v7.preference.EditTextPreferenceDialogFragmentCompat {

private EditText mEditText;
private int mInputType;

public static EditTextPreferenceDialogFragmentCompat newInstance(String key, int inputType) {
    EditTextPreferenceDialogFragmentCompat fragment = new EditTextPreferenceDialogFragmentCompat();
    Bundle b = new Bundle(2);
    b.putString("key", key);
    b.putInt("inputType", inputType);
    fragment.setArguments(b);
    return fragment;
}

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    mInputType = this.getArguments().getInt("inputType");
}

protected void onBindDialogView(View view) {
    this.mEditText = view.findViewById(android.R.id.edit);
    mEditText.setInputType(mInputType);
    super.onBindDialogView(view);
}

}

Then make your activity implements PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback

Use your EditTextPreferenceDialogFragmentCompat instead of android.support.v7.preference.EditTextPreferenceDialogFragmentCompat

public boolean onPreferenceDisplayDialog(@NonNull PreferenceFragmentCompat preferenceFragmentCompat, Preference preference) {
String key = preference.getKey();
if (/**show your dialog*/) {
    EditTextPreferenceDialogFragmentCompat f = EditTextPreferenceDialogFragmentCompat.newInstance(preference.getKey(), InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED);
    f.setTargetFragment(this, 0);
    f.show(getFragmentManager(), "android.support.v14.preference.PreferenceFragment.DIALOG");
    return true;
}
return false;

}

just use android.support.v7.preference.EditTextPreference in xml

<android.support.v7.preference.PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">
    <android.support.v7.preference.EditTextPreference
        .../>
</android.support.v7.preference.PreferenceScreen>
Jadwigajae answered 29/12, 2018 at 5:26 Comment(0)
F
2

For androidx library i used

    val preference = findPreference("pref_key") as EditTextPreference?
    
    preference!!.setOnBindEditTextListener { 
            editText -> editText.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED
    }

inside onCreatePreferences function for PreferenceFragmentCompat

Francophobe answered 30/4, 2021 at 7:46 Comment(0)
P
2

Still the same issue in 2021 with AndroidX... I fixed it by copying "EditTextPreference.java" class from the specified link in accepted answer then used it instead of androidx.preference.EditTextPreference on my XML preference screens

package myapp.preferences;

import android.content.Context;
import android.text.InputType;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.widget.EditText;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.collection.SparseArrayCompat;

import com.averydennison.containertracking.R;

public class EditTextPreference extends androidx.preference.EditTextPreference {
    @Nullable
    private OnBindEditTextListener onBindEditTextListener;

    private SparseArrayCompat<TypedValue> editTextAttributes = new SparseArrayCompat<>();

    private boolean disableMessagePaddingFix;

    @SuppressWarnings("unused")
    public EditTextPreference(Context context) {
        this(context, null);
    }

    @SuppressWarnings("WeakerAccess")
    public EditTextPreference(Context context, AttributeSet attrs) {
        this(context, attrs, R.attr.editTextPreferenceStyle);
    }

    @SuppressWarnings("WeakerAccess")
    public EditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
        this(context, attrs, defStyleAttr, 0);
    }

    @SuppressWarnings("WeakerAccess")
    public EditTextPreference(Context context, final AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);

        //TypedArray a = getContext().obtainStyledAttributes(
        //        attrs, R.styleable.EditTextPreference, defStyleAttr, defStyleRes);
        //disableMessagePaddingFix = a.getBoolean(R.styleable.EditTextPreference_pref_disableMessagePaddingFix, false);
        //a.recycle();

        processAttrs(attrs);

        super.setOnBindEditTextListener(new OnBindEditTextListener() {
            @Override
            public void onBindEditText(@NonNull EditText editText) {
                if (!disableMessagePaddingFix) {
                    fixMessagePadding(editText);
                }

                int n = editTextAttributes.size();
                for (int i = 0; i < n; i++) {
                    int attr = editTextAttributes.keyAt(i);
                    TypedValue value = editTextAttributes.valueAt(i);

                    int data = value.data;
                    // TODO resolve resources?

                    switch (attr) {
                        case android.R.attr.inputType:
                            editText.setInputType(data);
                            break;
                        case android.R.attr.textAllCaps:
                            editText.setAllCaps(data == 1);
                            break;
                        case android.R.attr.lines:
                            editText.setLines(data);
                            break;
                        case android.R.attr.minLines:
                            editText.setMinLines(data);
                            break;
                        case android.R.attr.maxLines:
                            editText.setMaxLines(data);
                            break;
                        case android.R.attr.ems:
                            editText.setEms(data);
                            break;
                        case android.R.attr.minEms:
                            editText.setMinEms(data);
                            break;
                        case android.R.attr.maxEms:
                            editText.setMaxEms(data);
                            break;
                    }
                }

                if (onBindEditTextListener != null) {
                    onBindEditTextListener.onBindEditText(editText);
                }
            }
        });
    }

    private void fixMessagePadding(@NonNull View view) {
        ViewParent parent = view.getParent();
        if (parent instanceof ViewGroup) {
            View msgView = ((ViewGroup) parent).findViewById(android.R.id.message);

            if (msgView != null) {
                ViewGroup.LayoutParams layoutParams = msgView.getLayoutParams();

                if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
                    ViewGroup.MarginLayoutParams marginLayoutParams = (ViewGroup.MarginLayoutParams) layoutParams;
                    marginLayoutParams.bottomMargin = 0;
                    msgView.setLayoutParams(marginLayoutParams);
                }
            }
        }
    }

    private void processAttrs(AttributeSet attributeSet) {
        if (attributeSet == null) {
            return;
        }

        int n = attributeSet.getAttributeCount();

        for (int i = 0; i < n; i++) {
            int nameRes = attributeSet.getAttributeNameResource(i);
            int resId = attributeSet.getAttributeResourceValue(i, 0);

            TypedValue value = null;

            switch (nameRes) {
                case android.R.attr.inputType:
                    value = new TypedValue();
                    value.resourceId = resId;
                    value.data = attributeSet.getAttributeIntValue(i, InputType.TYPE_CLASS_TEXT);
                    value.type = TypedValue.TYPE_INT_HEX;
                    break;
                case android.R.attr.minEms:
                case android.R.attr.maxEms:
                case android.R.attr.ems:
                case android.R.attr.minLines:
                case android.R.attr.maxLines:
                case android.R.attr.lines:
                    value = new TypedValue();
                    value.resourceId = resId;
                    value.data = attributeSet.getAttributeIntValue(i, -1);
                    value.type = TypedValue.TYPE_INT_DEC;
                    break;
                case android.R.attr.textAllCaps:
                    value = new TypedValue();
                    value.resourceId = resId;
                    value.data = attributeSet.getAttributeBooleanValue(i, false) ? 1 : 0;
                    value.type = TypedValue.TYPE_INT_BOOLEAN;
                    break;
            }

            if (value != null) {
                editTextAttributes.put(nameRes, value);
            }
        }
    }

    /**
     * Returns the {@link OnBindEditTextListener} used to configure the {@link EditText}
     * displayed in the corresponding dialog view for this preference.
     * <p>
     * NOTE that this will return the internal {@link OnBindEditTextListener} instead of the one set
     * via {@link #setOnBindEditTextListener(OnBindEditTextListener)}.
     *
     * @return The {@link OnBindEditTextListener} set for this preference, or {@code null} if
     * there is no OnBindEditTextListener set
     * @see OnBindEditTextListener
     */
    @Nullable
    //@Override
    public OnBindEditTextListener getOnBindEditTextListener() {
        return this.onBindEditTextListener;
        //return super.getOnBindEditTextListener();
    }

    @Override
    public void setOnBindEditTextListener(@Nullable OnBindEditTextListener onBindEditTextListener) {
        this.onBindEditTextListener = onBindEditTextListener;
    }

    @Deprecated
    public EditText getEditText() {
        throw new UnsupportedOperationException("Use OnBindEditTextListener to modify the EditText");
    }

    @Override
    public void setText(String text) {
        String oldText = getText();
        super.setText(text);
        if (!TextUtils.equals(text, oldText)) {
            notifyChanged();
        }
    }
}
Ponzo answered 29/5, 2021 at 2:10 Comment(0)
L
1

It happens when using android.support.v14.preference.PreferenceFragment or android.support.v7.preference.PreferenceFragmentCompat even after choosing android:inputType="numberDecimal". This issue could be overcome by using android.preference.PreferenceFragment. Unfortunately, it's deprecated in API level 28.

Even refactoring to AndroidX, using androidx.preference.PreferenceFragment or androidx.preference.PreferenceFragmentCompat didn't fix the issue.

Luthuli answered 16/3, 2019 at 16:52 Comment(1)
I am using the currently-recommended implementation "androidx.preference:preference:1.1.0". Not only is android:inputType ignored but I notice that android:hint and therefore probably others are also ignored. This question needs an updated answer explaining the failing XMLExtravascular
M
1

Unfortunately, in androidx.Preference (at least at androidx.preference:preference-ktx:1.1.1) the inputType is not working.

I had to load the xml resource twice:

class SettingsFragment : PreferenceFragmentCompat() {
  override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
    preferenceManager.sharedPreferencesName = "alex"
    setPreferencesFromResource(R.xml.root_preferences, rootKey)
    val xml = resources.getXml(R.xml.root_preferences)
    while (xml.eventType != XmlPullParser.END_DOCUMENT) {
      xml.parseInputType()
      xml.next()
    }
  }
}

I used a helper extension function:

private fun XmlPullParser.parseInputType(preferenceManager: androidx.preference.PreferenceManager) {
  if (eventType == XmlPullParser.START_TAG && name == "EditTextPreference") {
    val dictionary = HashMap<String, String>()
    for (i in 0 .. attributeCount-1) {
      dictionary.put(getAttributeName(i), getAttributeValue(i))
    }
    val name = dictionary["key"] ?: return
    val pref = preferenceManager.findPreference<EditTextPreference>(name) ?: return
    val inputType = Integer.decode(attributes["inputType"] ?: "1")

    if (inputType != 0) {
      pref.setOnBindEditTextListener { editText -> 
        editText.inputType = inputType
      }
    }
  }
}
Mendel answered 6/4, 2021 at 21:5 Comment(0)
E
0

You can retrieve the EditText from the Preference and from there setInputTypes or use KeyListeners to inform the keyboard:

EditText et = (EditText) editTextPref.getEditText();
et.setKeyListener(DigitsKeyListener.getInstance());

found the answer on older thread

Ellerey answered 15/3, 2017 at 9:7 Comment(1)
Unfortunately, the android.support.v7.preference version of EditTextPreference no longer has this method :-(Maximilien
U
0

Thought I'd add my solution for Android-TV in case someone gets here and needs it. android_su's reply put me in the right direction, unfortunately, the LeanbackEditTextPreferenceDialogFragmentCompat doesn't support OnPreferenceDisplayDialogCallback. Instead I had to:

override onCreateView and implement a new newInstance function for LeanbackEditTextPreferenceDialogFragmentCompat using inheritance:

public static class TvPreferencesDialog extends LeanbackEditTextPreferenceDialogFragmentCompat {

    public static TvPreferencesDialog newInstance(String key) {
        final Bundle args = new Bundle(1);
        args.putString(ARG_KEY, key);

        final TvPreferencesDialog fragment = new TvPreferencesDialog();
        fragment.setArguments(args);

        return fragment;
    }

    @Override
    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        View root = super.onCreateView(inflater, container, savedInstanceState);
        final String key = getArguments().getString(ARG_KEY);
        EditText editTextView = root.findViewById(android.R.id.edit);

        if (key.equalsIgnoreCase("some pref key 1")) {
            editTextView.setInputType(InputType.TYPE_NUMBER_FLAG_DECIMAL);
        } else if (key.equalsIgnoreCase("some pref key 2")) {
            editTextView.setInputType(InputType.TYPE_CLASS_NUMBER);
            editTextView.addTextChangedListener(new MyTextWatcher());
        }

        return root;
    }    
}

override onPreferenceDisplayDialog inside my LeanbackSettingsFragmentCompat:

@Override
public boolean onPreferenceDisplayDialog(@NonNull PreferenceFragmentCompat caller, Preference pref) {
    if (caller == null) {
        throw new IllegalArgumentException("Cannot display dialog for preference " + pref + ", Caller must not be null!");
    }
    final Fragment f;
    if (pref instanceof EditTextPreference) {
        f = TvPreferencesDialog.newInstance(pref.getKey());
        f.setTargetFragment(caller, 0);
        startPreferenceFragment(f);
        return true;
    } else {
        return super.onPreferenceDisplayDialog(caller, pref);
    }
}
Ulceration answered 20/5, 2019 at 17:59 Comment(0)
A
-3

EditTextPreference widgets should take the same attributes as a regular EditText, so use:

android:inputType="number"
Arcanum answered 15/3, 2017 at 8:50 Comment(1)
it didn't change anything, still allows me type textFife

© 2022 - 2024 — McMap. All rights reserved.