4

我在 PreferenceActivity 中需要 AutoCompliteTextView,所以我扩展了 DialogPreference。我的自动完成期望(帮助)用户输入国家/地区名称。如果用户按取消或不输入任何值,我很好,但是我想确保在关闭对话框之前输入正确的名称。我试图将 onClick 覆盖为


@Override
public void onClick(DialogInterface dialog, int which) {
        if (!validator.isValid(textView.toString())) {
            onDialogClosed(false);
        } else {
            //do something here
            super.onClick(dialog, which);
        }
    }

也与 onDialogClosed


@Override
    protected void onDialogClosed(boolean positiveResult) {
        if (validator.isValid(textView.toString())) {
            //do something here
            super.onDialogClosed(positiveResult);
        }
    }
4

5 回答 5

9

我还遇到了一个问题,即在关闭首选项对话框之前,Android 没有提供内置方法来检查新输入的首选项值。在对话框关闭后进行检查(boolean onPreferenceChange完成的内容),只能发现该值不正确,应用程序应该阻止它被保存,但这似乎很不方便。试想一下,一个用户打错了,新值没有保存,但是对话框关闭了,用户被告知他/她必须从头开始重复这个过程。它肯定应该被修复。

当遇到编程中的问题时,最好提供解决方案的代码。这就是为什么我要发布答案并准备好复制和粘贴的解决方案。它遵循上述答案之一的明显想法,而它不像其他提供的代码片段所暗示的那样处理反射。

public class CustomEditTextPreference extends EditTextPreference
{
  // if true, this preference requires new values to be checked for conformance to e-mail syntax
  private boolean isEmail = false; 

  public CustomEditTextPreference(Context context, AttributeSet attrs)
  {
    super(context, attrs);

    // set isEmail either from custom XML-attributes (look up through attrs)
    // or just by key
    // if(getKey().equals(KNOWN_EMAIL_PREF))
    //   isEmail = true;
  }

  /**
   * Checks if newValue conforms to a specific rule/syntax.
   * Returns error code equal to resource ID of corresponding error message if the value is incorrect,
   * or 0 if the validation was successful
   *
   * @param  newValue  a string with new preference value that needs a check-up
   * @return    integer error code equal to error message resource id
   */
  private int isValid(String newValue)
  {
    int result = 0; // no error

    if(isEmail) 
    {
      if(!android.util.Patterns.EMAIL_ADDRESS.matcher(newValue).matches())
      {
        result = R.string.invalid_email;
      }
    }
    // ...
    // other check-ups if necessary

    return result;
  }

  @Override
  protected void showDialog(Bundle state)
  {       
    super.showDialog(state);

    final AlertDialog d = (AlertDialog)getDialog();

    final EditText edit = getEditText();

    d.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(new View.OnClickListener()
    {            
      @Override
      public void onClick(View v)
      {
        int errorCode = isValid(edit.getText().toString());
        Boolean canCloseDialog = (errorCode == 0);

        if(canCloseDialog)
        {
          d.dismiss();
          onDialogClosed(true);
        }
        else
        {
          String errorMessage = getContext().getString(errorCode);
          Toast t = Toast.makeText(getContext(), errorMessage, Toast.LENGTH_LONG);
          t.setGravity(Gravity.CENTER, 0, 0);
          t.show();
        }
      }
    });
  }
}

我认为代码几乎是不言自明的。如果用户用不正确的电子邮件填写该字段,然后按确定按钮,则对话框保持打开状态并通过 toast 显示错误消息。

于 2013-11-11T17:09:34.033 回答
6

实际上,通过使用reflection,我实现了您所说的。

@Override
public void onClick(DialogInterface dialog, int which) {
    if(!validate(arg)){
        try {
            // do not close
            Field field = dialog.getClass().getSuperclass()
                    .getDeclaredField("mShowing");
            field.setAccessible(true);
            field.set(dialog, false);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
于 2013-04-13T08:03:10.030 回答
4

一旦用户单击对话框按钮,对话框就会关闭,您无法阻止它。

我能想到的唯一可以尝试的方法是调用getDialog()DialogPreference将其转换为AlertDialog,然后调用getButton()以检索您的肯定按钮,然后禁用它,稍后在输入有效时启用它。

于 2012-04-01T19:27:32.677 回答
2

如果您想在对话框中显示一些错误而不是禁用按钮,那么您需要创建一个扩展 EditTextPreference 的类 CustomEditTextPreference

下面是代码片段

public class CustomEditTextPreference extends EditTextPreference  {
EditText setPasswordEditText;
private Context context;
AlertDialog alertDialog;

public CustomEditTextPreference(Context context, AttributeSet attrs) {
    super(context, attrs);
    this.context = context;
    setPasswordEditText = this.getEditText();
}

@Override
protected void showDialog(Bundle state) {
    super.showDialog(state);

    alertDialog = (AlertDialog) getDialog();
    alertDialog.setCanceledOnTouchOutside(false);
    Button positiveButton = alertDialog
            .getButton(AlertDialog.BUTTON_POSITIVE);
    positiveButton.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            String str = setPasswordEditText.getText().toString();
            if (/*condition not met*/) {
                showError();
            } else {
                alertDialog.dismiss();
            }

        }
    });

}
于 2014-02-18T09:36:46.207 回答
1

您可以覆盖 DialogPreference 中的 onPrepareDialogBu​​ilder()

于 2014-10-02T04:42:11.867 回答