EditTextPreference - 只有数值 inputType - 不工作
EditTextPreference - only numeric value inputType - isn't working
<android.support.v7.preference.EditTextPreference
android:key="prefTest"
android:title="test number input"
android:inputType="numberDecimal|numberSigned"
android:defaultValue="800"/>
它仍然显示常规键盘并允许我输入任何字符
android.support.v7
有什么问题吗?
EditTextPreference 小部件应采用与常规 EditText 相同的属性,因此请使用:
android:inputType="number"
android:digits="0123456789"
在 edittext 中使用它,因为它只接受定义的数字。如果它不起作用,则使用 Android-Support-Preference-V7-Fix 库。
修复了 EditTextPreference 将 XML 属性(如 inputType)转发给 EditText,就像原来的首选项一样。
您可以从首选项中检索 EditText,然后从那里设置输入类型或使用 KeyListeners 通知键盘:
EditText et = (EditText) editTextPref.getEditText();
et.setKeyListener(DigitsKeyListener.getInstance());
found the answer on older thread
我同意原来的支持偏好有一些问题,但为了解决这个问题,我们只需要添加自定义布局并指定 EditText 为 android:inputType="number"
<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>
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);
}
}
然后让你的activity实现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>
使用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时会出现这种情况。不幸的是,它在 API 级别 28 中已弃用。
即使重构到 AndroidX,使用 androidx.preference.PreferenceFragment or androidx.preference.PreferenceFragmentCompat 也没有解决问题。
我想我会为 Android-TV 添加我的解决方案,以防有人到达这里并需要它。
android_su 的回复让我找到了正确的方向,不幸的是,LeanbackEditTextPreferenceDialogFragmentCompat
不支持 OnPreferenceDisplayDialogCallback
。
相反,我不得不:
覆盖 onCreateView
并使用继承为 LeanbackEditTextPreferenceDialogFragmentCompat
实现一个新的 newInstance
函数:
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);
}
}
开发人员设置指南中的 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 中将输入类型定义为 "number",但仍然得到带字母的普通键盘。这种方法对我有用。
不幸的是,在 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
}
}
}
}
对于我使用的 androidx 库
val preference = findPreference("pref_key") as EditTextPreference?
preference!!.setOnBindEditTextListener {
editText -> editText.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED
}
内部 onCreatePreferences
函数 PreferenceFragmentCompat
AndroidX 在 2021 年仍然存在同样的问题...我通过复制“EditTextPreference.java”修复了它 class from the specified link in accepted answer 然后在我的 androidx.preference.EditTextPreference 上使用它而不是 androidx.preference.EditTextPreference XML 首选项屏幕
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();
}
}
}
<android.support.v7.preference.EditTextPreference
android:key="prefTest"
android:title="test number input"
android:inputType="numberDecimal|numberSigned"
android:defaultValue="800"/>
它仍然显示常规键盘并允许我输入任何字符
android.support.v7
有什么问题吗?
EditTextPreference 小部件应采用与常规 EditText 相同的属性,因此请使用:
android:inputType="number"
android:digits="0123456789"
在 edittext 中使用它,因为它只接受定义的数字。如果它不起作用,则使用 Android-Support-Preference-V7-Fix 库。
修复了 EditTextPreference 将 XML 属性(如 inputType)转发给 EditText,就像原来的首选项一样。
您可以从首选项中检索 EditText,然后从那里设置输入类型或使用 KeyListeners 通知键盘:
EditText et = (EditText) editTextPref.getEditText();
et.setKeyListener(DigitsKeyListener.getInstance());
found the answer on older thread
我同意原来的支持偏好有一些问题,但为了解决这个问题,我们只需要添加自定义布局并指定 EditText 为 android:inputType="number"
<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>
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);
}
}
然后让你的activity实现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>
使用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时会出现这种情况。不幸的是,它在 API 级别 28 中已弃用。
即使重构到 AndroidX,使用 androidx.preference.PreferenceFragment or androidx.preference.PreferenceFragmentCompat 也没有解决问题。
我想我会为 Android-TV 添加我的解决方案,以防有人到达这里并需要它。
android_su 的回复让我找到了正确的方向,不幸的是,LeanbackEditTextPreferenceDialogFragmentCompat
不支持 OnPreferenceDisplayDialogCallback
。
相反,我不得不:
覆盖 onCreateView
并使用继承为 LeanbackEditTextPreferenceDialogFragmentCompat
实现一个新的 newInstance
函数:
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);
}
}
开发人员设置指南中的 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 中将输入类型定义为 "number",但仍然得到带字母的普通键盘。这种方法对我有用。
不幸的是,在 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
}
}
}
}
对于我使用的 androidx 库
val preference = findPreference("pref_key") as EditTextPreference?
preference!!.setOnBindEditTextListener {
editText -> editText.inputType = InputType.TYPE_CLASS_NUMBER or InputType.TYPE_NUMBER_FLAG_SIGNED
}
内部 onCreatePreferences
函数 PreferenceFragmentCompat
AndroidX 在 2021 年仍然存在同样的问题...我通过复制“EditTextPreference.java”修复了它 class from the specified link in accepted answer 然后在我的 androidx.preference.EditTextPreference 上使用它而不是 androidx.preference.EditTextPreference XML 首选项屏幕
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();
}
}
}