Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Do not close DialogPreference onClick if condition not met

I have need for AutoCompliteTextView in PreferenceActivity so I extended DialogPreference. My auto-complite is expecting from (helping) user to enter country name. I'm fine if user press Cancel or enters no values, however I would like to ensure that proper name is entered before dialog is closed. 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);
        }
    }
like image 442
peter_budo Avatar asked Nov 29 '22 02:11

peter_budo


1 Answers

I also faced the problem, that Android does not provide a built-in way to check up a newly entered preference value BEFORE the preference dialog is closed. A check up performed after the dialog is closed (what the boolean onPreferenceChange accomplishes), can only discover that the value is incorrect and the app should prevent it from being saved, but this seems rather inconvenient. Just imagine that a user made a typo, new value is not saved, but the dialog is closed, and the user is informed that he/she must repeat the process from very beginning. It surely should be fixed.

When it comes to a problem in programming, it's better to provide a code for solution. This is why I'm posting the answer with the solution ready for copy&paste. It follows the obvious idea from one of the answers above, whereas it does not deal with reflections as the other provided code-snippet implies.

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 is pretty much self-explaining. If a user fills in the field with incorrect e-mail, and presses OK button, then the dialog remains open and an error message is shown via toast.

like image 102
Stan Avatar answered Dec 01 '22 15:12

Stan