1

我是完成数字偏好验证例程的一小步。
如果条目不是数字,我替换了 ClickListener 上的 EditTextPrefernce OK 按钮以防止离开对话框。
我使用 TextWatcher.afterTextChanged 检查条目是否为数字,并将有效的评估放在 EditText 标记上。
一切正常,输入无效时按 OK 不会离开对话框,输入有效时按 OK...这里我需要调用原始的 OK 按钮 onClick但我没有找到如何操作有 View 函数 callOnClick() 和 performOnClick(),但我查看了它们的代码,它们旨在调用已安装的侦听器,而不是原始侦听器。

@Override
public void onCreate(Bundle savedInstanceState) {
    Log.d(TAG, "+ onCreate(savedInstanceState:" + savedInstanceState + ")");
    super.onCreate(savedInstanceState);

    ...

    prefMaxLogs = (EditTextPreference) findPreference(getText(R.string.pref_maxLogs_key));
    prefMaxLogsEt = prefMaxLogs.getEditText();
    prefMaxLogsEt.setSingleLine();
    prefMaxLogsEt.setOnFocusChangeListener(ofcl);
    prefMaxLogsEt.addTextChangedListener(tw);

    ...

    Log.d(TAG, "- onCreate()");
}

private OnFocusChangeListener ofcl = new OnFocusChangeListener() {
    @Override
    public void onFocusChange(View v, boolean hasFocus) {
        Log.d(TAG, "+ onFocusChange(v:" + v + ", hasFocus:" + hasFocus + ")");
        if( hasFocus ) {
            prefMaxLogsEt.selectAll();
            Dialog dialog = prefMaxLogs.getDialog();
            if( dialog != null ) {
                dialog.findViewById(android.R.id.button1).setOnClickListener(ocl);
            }
        }
        Log.d(TAG, "- onFocusChange()");
    }
};

private OnClickListener ocl = new OnClickListener() {
    @Override
    public void onClick(View v) {
        Log.d(TAG, "+ onClick(v:" + v + ")");
        Boolean valid = !(Boolean) prefMaxLogsEt.getTag(R.string.invalidEntry);
        if( valid ) {
            Log.d(TAG, "Valid et");
        } 
        Log.d(TAG, "- onClick()");
    }
};

private TextWatcher tw = 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 s) {
        Log.d(TAG, "+ afterTextChanged(s:" + s + ")");
        String source = s.toString();
        //prefMaxLogsEt.removeTextChangedListener(this);
        if( !source.matches("^[0-9]+$") ) {
            prefMaxLogsEt.getBackground().setColorFilter(getResources().getColor(R.color.invalid), Mode.SRC_IN);
            prefMaxLogsEt.invalidate();
            prefMaxLogsEt.setError(getText(R.string.invalidEntry));
            prefMaxLogsEt.selectAll();
            prefMaxLogsEt.setTag(R.string.invalidEntry, true);
        } else {
            prefMaxLogsEt.setError(null);
            prefMaxLogsEt.getBackground().clearColorFilter();
            prefMaxLogsEt.invalidate();
            prefMaxLogsEt.setTag(R.string.invalidEntry, false);
        }
        //prefMaxLogsEt.addTextChangedListener(this);
        Log.d(TAG, "- afterTextChanged()");
    }
};

当 EditText 获得焦点时设置 onClickListener,因为我知道对话框已经显示。
onClickListener 防止对话框因无效条目而关闭

4

1 回答 1

1

我找到了另一种验证 EditTextPreference 的方法。设置 OnPreferenceChangeListener 并实现 onPreferenceChange。

@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
    Log.d(TAG, "+ onPreferenceChange(preference:" + preference + ", newValue:" + newValue + ")");
    Boolean rv = true;
    if( preference.equals(prefMaxLogs) ) {
        String source = newValue.toString();
        if( !source.matches("^[0-9]+$") ) {
            rv = false;
        }
    }
    Log.d(TAG, "- onPreferenceChange()");
    return rv;
}

此函数的优点是它返回一个布尔值,如果您接受更改,则返回 true,如果您拒绝更改,则返回 false。
我为 OK 按钮删除了 onFocusListener 和 onClickListener,这种方式更简单。
我仍然使用 setColorFilter 和 afterTextChanged 来警告用户输入无效。如果用户按 OK,对话框将关闭,但只接受有效值。

这个监听器是为每个首选项单独设置的,所以这是我在 onCreate() 中的初始化

    prefMaxLogs = (EditTextPreference) findPreference(getText(R.string.pref_maxLogs_key));
    prefMaxLogsEt = prefMaxLogs.getEditText();
    prefMaxLogsEt.setSingleLine();
    prefMaxLogsEt.addTextChangedListener(tcl);
    prefMaxLogs.setOnPreferenceClickListener(this);
于 2013-02-22T14:41:20.853 回答