如果条件不满足,请不要关闭DialogPreference onClick

时间:2012-04-01 18:15:30

标签: android onclick dialog-preference

我需要在PreferenceActivity中使用AutoCompliteTextView,因此我扩展了DialogPreference。我的auto-complite期待(帮助)用户输入国家/地区名称。我很好,如果用户按下取消或没有输入值,但我想确保在关闭对话框之前输入正确的名称。我试图将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);
        }
    }

5 个答案:

答案 0 :(得分: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显示错误消息。

答案 1 :(得分: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();
        }
    }
}

答案 2 :(得分:4)

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

我能想到的唯一可以尝试的是在getDialog()上拨打DialogPreference,将其转换为AlertDialog,然后拨打getButton()以取回您的积极信息按钮,并禁用它,稍后在输入有效时启用它。

答案 3 :(得分: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();
            }

        }
    });

}

答案 4 :(得分:1)

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