2012-04-01 4 views
2

У меня есть необходимость в AutoCompliteTextView в PreferenceActivity, поэтому я расширил DialogPreference. Мой автокомплекс ожидает от пользователя (помогающего) ввести название страны. Я в порядке, если пользователь нажимает «Отмена» или не вводит никаких значений, однако я бы хотел, чтобы имя пользователя было введено до закрытия диалогового окна. Я попытался переопределить OnClick, какНе закрывать 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); 
     } 
    } 

ответ

3

Когда пользователь нажимает на кнопку диалога, диалог закрывается, и нет ничего, что вы можете сделать, чтобы остановить его.

Единственное, что я могу думать о том, что вы могли бы попробовать это назвать getDialog() на DialogPreference, отлитый что AlertDialog, а затем вызвать getButton(), чтобы получить ваш положительный результат кнопку, и отключить его, позволяя ему позже, когда вход активен.

+0

Я не вижу, где это должно быть сделано, onCreateDialogView и onPrepareDialogBuilder слишком рано, так как диалог просто создается, поэтому null, onClick слишком поздно, так как нажатие кнопки происходит. Я что-то упускаю? –

+0

@peter_budo: Если ничего другого, вам не хватает первых 11 слов моего второго абзаца: «Единственное, что я могу думать о том, что вы могли бы попробовать». Я никогда не пытался наложить валидацию на «DialogPreference». Однако 'onBindDialogView() и' showDialog() 'выглядят как кандидаты, которые стоит попробовать. – CommonsWare

+0

Я видел это, я просто пытаюсь получить некоторый разумный пользовательский опыт (по крайней мере, я), поскольку я считаю, что просто предоставление пользователям ListView или Spinner из таких стран, как Соединенное Королевство или Соединенные Штаты, будет ненавидеть меня, поскольку они находятся где-то в конец 230 + длинный список стран. –

6

Фактически, используя отражение, я достиг того, что вы сказали.

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

}

+0

это полностью работает! – jmacboy

8

я также столкнулся с проблемой, что 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(); 
     } 
     } 
    }); 
    } 
} 

Я думаю, что код в значительной степени объясняет себя. Если пользователь заполняет поле с неправильной электронной почтой и нажимает кнопку «ОК», диалог остается открытым, и сообщение об ошибке отображается с помощью тоста.

2

Если вы хотите, чтобы показать некоторые ошибки в диалоге вместо отключения кнопки, то вам необходимо создать класс CustomEditTextPreference, который расширяет EditTextPreference

ниже фрагмент кода

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

     } 
    }); 

} 
1

Вы можете переопределить onPrepareDialogBuilder() внутри диалогового окна DialogPreference