EditTextPreference - 只有数值inputType - 不起作用

时间:2017-03-15 08:45:58

标签: android android-support-library

var totalMinutes = new Date().getHours() * 60 + new Date().getMinutes();
if (totalMinutes >= 360 && totalMinutes <= 1200) {
   alert('good time');
} else {
    alert('bad time')
}

它仍然显示常规键盘并允许我键入任何字符

<android.support.v7.preference.EditTextPreference android:key="prefTest" android:title="test number input" android:inputType="numberDecimal|numberSigned" android:defaultValue="800"/> 是否有问题?

12 个答案:

答案 0 :(得分:5)

android:digits="0123456789"

在edittext中使用它,因为它只接受定义的数字。如果它不起作用,那么使用Android-Support-Preference-V7-Fix库。

修复了EditTextPreference将XML属性(如inputType)转发到EditText,就像原始首选项一样。

答案 1 :(得分:2)

开发人员设置指南中的Customize your settings部分建议您使用OnBindEditTextListener以编程方式设置输入类型,如下所示:

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);
                }
            });
        }
    }
}

我尝试在xml中将输入类型定义为“数字”,但仍然得到了带有字母的普通键盘。这种方法对我有用。

答案 2 :(得分:1)

android.support.v7.preference.EditTextPreference不包含getEditText()方法。

但是我们可以扩展android.support.v7.preference.EditTextPreferenceDialogFragmentCompat来设置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);
}

}

然后使您的活动实现PreferenceFragmentCompat.OnPreferenceDisplayDialogCallback

使用您的EditTextPreferenceDialogFragmentCompat代替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;

}

只需在XML中使用android.support.v7.preference.EditTextPreference

<android.support.v7.preference.PreferenceScreen
    xmlns:android="http://schemas.android.com/apk/res/android">
    <android.support.v7.preference.EditTextPreference
        .../>
</android.support.v7.preference.PreferenceScreen>

答案 3 :(得分:0)

您可以从首选项中检索EditText,然后从那里检索setInputTypes或使用KeyListeners来通知键盘:

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

found the answer on older thread

答案 4 :(得分:0)

我同意原始的支持首选项存在一些问题,但是要解决此问题,我们只需要添加自定义布局并使用android:inputType =“ number”指定EditText

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

这样您就可以复制原始的preference_dialog_layout.xml文件并进行编辑。

<?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>

答案 5 :(得分:0)

即使选择了android:inputType="numberDecimal",使用android.support.v14.preference.PreferenceFragmentandroid.support.v7.preference.PreferenceFragmentCompat时也会发生。使用android.preference.PreferenceFragment可以解决此问题。不幸的是,它已在API级别28中弃用。

使用androidx.preference.PreferenceFragmentandroidx.preference.PreferenceFragmentCompat甚至重构为AndroidX都无法解决问题。

答案 6 :(得分:0)

如果有人到达这里并需要它,我想为Android-TV添加我的解决方案。 android_su的回复将我带往了正确的方向,很遗憾,LeanbackEditTextPreferenceDialogFragmentCompat不支持OnPreferenceDisplayDialogCallback。 相反,我必须:

使用继承来覆盖onCreateView并为newInstance实现新的LeanbackEditTextPreferenceDialogFragmentCompat功能:

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;
    }    
}

在我的onPreferenceDisplayDialog内覆盖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);
    }
}

答案 7 :(得分:0)

不幸的是,在 androidx.Preference(至少在 androidx.preference:preference-ktx:1.1.1)中,inputType 不起作用。

我不得不两次加载 xml 资源:

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()
    }
  }
}

我使用了一个辅助扩展函数:

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
      }
    }
  }
}

答案 8 :(得分:0)

对于我使用的 androidx 库

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

onCreatePreferencesPreferenceFragmentCompat 函数内

答案 9 :(得分:0)

AndroidX 在 2021 年仍然存在同样的问题...我通过复制“EditTextPreference.java”类 from the specified link in accepted answer 来修复它,然后在我的 XML 首选项屏幕上使用它而不是 androidx.preference.EditTextPreference

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();
        }
    }
}

答案 10 :(得分:-1)

嘿试试这个只带数字的键盘

android:inputType="phone"

答案 11 :(得分:-3)

EditTextPreference小部件应采用与常规EditText相同的属性,因此请使用:

tf