я также столкнулся с проблемой, что 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();
}
}
});
}
}
Я думаю, что код в значительной степени объясняет себя. Если пользователь заполняет поле с неправильной электронной почтой и нажимает кнопку «ОК», диалог остается открытым, и сообщение об ошибке отображается с помощью тоста.
Я не вижу, где это должно быть сделано, onCreateDialogView и onPrepareDialogBuilder слишком рано, так как диалог просто создается, поэтому null, onClick слишком поздно, так как нажатие кнопки происходит. Я что-то упускаю? –
@peter_budo: Если ничего другого, вам не хватает первых 11 слов моего второго абзаца: «Единственное, что я могу думать о том, что вы могли бы попробовать». Я никогда не пытался наложить валидацию на «DialogPreference». Однако 'onBindDialogView() и' showDialog() 'выглядят как кандидаты, которые стоит попробовать. – CommonsWare
Я видел это, я просто пытаюсь получить некоторый разумный пользовательский опыт (по крайней мере, я), поскольку я считаю, что просто предоставление пользователям ListView или Spinner из таких стран, как Соединенное Королевство или Соединенные Штаты, будет ненавидеть меня, поскольку они находятся где-то в конец 230 + длинный список стран. –