Don't close the DialogPreference onClick if the condition is not met

I need AutoCompliteTextView in PreferenceActivity, so I extended DialogPreference. My autocomplex expects the user (helping) to enter the country name. I'm fine if the user clicks Cancel or doesn't enter any values, however I would like the username to be entered before closing the dialog. I tried to override onClick as


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

also with onDialogClosed


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

      

+3


source to share


5 answers


As soon as the user clicks on the dialog button, the dialog is closed and there is nothing you can do to stop it.



The only thing I can think of is call getDialog()

in DialogPreference

, assign it to AlertDialog

, then call getButton()

to retrieve your positive button, and disable it by enabling it later when the input is valid.

+3


source


I also ran into the problem that Android does not provide a built-in way to validate the newly entered preference value BEFORE the preferences dialog is closed. Checking after closing the dialog (which it does boolean onPreferenceChange

) can only detect that the value is incorrect and the application should prevent it from being saved, but that seems pretty awkward. Imagine that the user made a typo, the new value is not saved, but the dialog is closed and the user is told that he / she must repeat the process from the beginning. This definitely needs to be fixed.

When it comes to a programming problem, it's best to provide code to solve. This is why I am posting an answer with a ready-made copy and paste solution. This follows the obvious idea from one of the above answers, while it doesn't deal with reflexes as another, provided piece of code suggests.



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

      

I think the code pretty much explains itself. If the user fills in the field with the wrong email and clicks OK, the dialog remains open and the error message is displayed with a toast.

+8


source


In fact, using reflection, I achieved what you said.

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

      

}

+6


source


If you want to show some error in the dialog instead of disabling the button, you need to create a CustomEditTextPreference class that extends the EditTextPreference

below is a code snippet

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

        }
    });

}

      

+2


source


You can override onPrepareDialogBuilder () inside DialogPreference

+1


source







All Articles