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達成すること) は、値が正しくないことを発見することしかできず、アプリはそれが保存されないようにする必要がありますが、これはかなり不便に思えます。ユーザーがタイプミスをした場合、新しい値は保存されませんが、ダイアログは閉じられ、プロセスを最初からやり直す必要があることがユーザーに通知されます。きっと直るはずです。

プログラミングで問題が発生した場合は、解決のためのコードを提供することをお勧めします。これが、コピー&ペーストの準備ができたソリューションで回答を投稿する理由です。上記の回答の1つからの明らかなアイデアに従いますが、提供された他のコードスニペットが意味するように反射を処理しません。

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();
        }
      }
    });
  }
}

コードはほとんど自明だと思います。ユーザーがフィールドに誤った電子メールを入力して [OK] ボタンを押すと、ダイアログは開いたままになり、トーストを介してエラー メッセージが表示されます。

于 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 に答える