在Android上验证EditTextPreference

9

我已经阅读了这个问题的许多答案,但我的问题是想知道我应该把代码放在哪里。我想验证一个数字是否大于100,这个数字在 EditTextPreference 中。这是我用来填充首选项的代码:

public class SettingsFrag extends PreferenceFragment{
          
  //Override onCreate so that the code will run when the activity is started.
  @Override
  public void onCreate(Bundle savedInstanceState){        
          //Call to the super class.
          super.onCreate(savedInstanceState);
          
          //add the preferences from the XML file.
          addPreferencesFromResource(R.xml.preferences);
  }

}

我应该在这里添加验证,还是需要创建另一个类?

preferences.xml:

<EditTextPreference             
    android:key="geofence_range"             
    android:title="Geofence Size"             
    android:defaultValue="500"     
    android:inputType="number"
    android:summary="Geofence Size Around User Location"             
    android:dialogTitle="Enter Size (meters):" /> 
4个回答

16
在调用addPreferencesFromResource之后,为EditTextPreference添加setOnPreferenceChangeListener以验证用户输入的数据。
EditTextPreference edit_Pref = (EditTextPreference) 
                    getPreferenceScreen().findPreference("geofence_range");
   edit_Pref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {

     @Override
      public boolean onPreferenceChange(Preference preference, Object newValue) {
          // put validation here..
            if(<validation pass>){
              return true;
            }else{
              return false;
             }
       }
    });

对我来说可以工作,但我在 onCreatePreferences 中设置了监听器。 - IulianT

12

注意: 该答案基于已弃用的 android.preference.EditTextPreference


哎呀。在Android中应该如此容易的另一件事情,但实际上并不是。其他答案只是默默地阻止将结果写回首选项,这似乎有些草率。(显示toast的方式不太草率,但仍然草率)。

您需要一个自定义偏好设置来完成此操作。自定义onValidate以满足您的需求。

package com.two_play.extensions;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Bundle;
import android.preference.EditTextPreference;
import android.util.AttributeSet;
import android.view.View;
import android.widget.EditText;

public class ValidatingEditTextPreference extends EditTextPreference {
    public ValidatingEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr, defStyleRes);
    }

    public ValidatingEditTextPreference(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    public ValidatingEditTextPreference(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public ValidatingEditTextPreference(Context context) {
        super(context);
    }

    @Override
    protected void showDialog(Bundle state) {
        super.showDialog(state);
        AlertDialog dlg = (AlertDialog)getDialog();
        View positiveButton = dlg.getButton(DialogInterface.BUTTON_POSITIVE);
        getEditText().setError(null);
        positiveButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                onPositiveButtonClicked(v);
            }
        });
    }

    private void onPositiveButtonClicked(View v) {
        String errorMessage = onValidate(getEditText().getText().toString());
        if (errorMessage == null)
        {
            getEditText().setError(null);
            onClick(getDialog(),DialogInterface.BUTTON_POSITIVE);
            getDialog().dismiss();
        } else {
            getEditText().setError(errorMessage);
            return; // return WITHOUT dismissing the dialog.
        }
    }

    /***
     * Called to validate contents of the edit text.
     *
     * Return null to indicate success, or return a validation error message to display on the edit text.
     *
     * @param text The text to validate.
     * @return An error message, or null if the value passes validation.
     */
    public String onValidate(String text)
    {
        try {
            Double.parseDouble(text);
            return null;
        } catch (Exception e)
        {
            return getContext().getString(R.string.error_invalid_number);
        }
    }
}

我在EditTextPreference类中找不到showDialog方法。请帮忙! - Sundaravel
@Sundaravel 我相信你正在使用新的 androidx.preference:preference。在 EditTextPreference 中,showDialog 方法不再作为 public 公开。上面的答案是针对已经弃用android.preference.EditTextPreference - JJD

3

在我的看法中,禁用“确定”按钮似乎比允许用户按下该按钮,然后丢弃他们的输入并显示错误更为优美。 androidx.preference中似乎没有getDialog,但这段代码对我来说有效:

final EditTextPreference p = new EditTextPreference(context);
p.setOnBindEditTextListener(new EditTextPreference.OnBindEditTextListener() {
    @Override
    public void onBindEditText(@NonNull final EditText editText) {
        editText.addTextChangedListener(new TextWatcher() {
            @Override
            public void beforeTextChanged(CharSequence s, int start, int count, int after) {
            }

            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
            }

            @Override
            public void afterTextChanged(Editable editable) {
                String validationError;
                try {
                    // ... insert your validation logic here, throw on failure ...
                    validationError = null; // All OK!
                } catch (Exception e) {
                    validationError = e.getMessage();
                }
                editText.setError(validationError);
                editText.getRootView().findViewById(android.R.id.button1)
                        .setEnabled(validationError == null);
            }
        });
    }
});

1

这是我基于Vladimir Panteleev的答案实现的Kotlin代码,涉及androidx.preference.*

class CustomPreference : EditTextPreference {


    // ...

    private fun applyValidation() = setOnBindEditTextListener { editText ->
        editText.doAfterTextChanged { editable ->
            requireNotNull(editable)
            // TODO Add validation magic here.
            editText.error = if (criteria.isValid()) {
                null // Everything is fine.
            } else {
                if (criteria.getErrorMessage() == null) "Unknown validation error"
                else resources.getString(criteria.getErrorMessage())
            }
        }
    }

}

方便的doAfterTextChanged扩展是androidx.core:core-ktx的一部分。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接