Итак, у меня есть диалог, в котором пользователь вводит данные, вот возраст пользователя. Поэтому мне бы хотелось, чтобы когда/если пользователь покидает текст edittext, edittext будет делать анимацию встряски, как в демонстрациях api. До сих пор я не могу заставить диалог не отклоняться, когда вводится неверная информация. Спасибо.
mInflater = (LayoutInflater) Information.this.getSystemService(LAYOUT_INFLATER_SERVICE);
mLayout = mInflater.inflate(R.layout.agedialog, null);
mAgeEditText = (EditText) mLayout.findViewById(R.id.AgeEditText);
mAgeResultTextView = (TextView) findViewById(R.id.AgeResultTextView);
final Animation shake = AnimationUtils.loadAnimation(Information.this, R.anim.shake);
mInputManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
mInputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
new AlertDialog.Builder(Information.this).setView(mLayout).setTitle(R.string.EnterYourAge)
.setPositiveButton(R.string.OK, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mInputManager.hideSoftInputFromWindow(mAgeEditText.getWindowToken(), 0);
if (TextUtils.isEmpty(mAgeEditText.getText())) {
mAgeEditText.startAnimation(shake);
// here the dialog dismisses even if I call startAnimation
}
else {
HelperClass.getInstance().setAge(Integer.parseInt(mAgeEditText.getText().toString()));
mAgeResultTextView.setText(HelperClass.getInstance().getAge());
}
}
}).setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
mInputManager.hideSoftInputFromWindow(mAgeEditText.getWindowToken(), 0);
dialog.cancel();
}
}).show();
Хорошо, поэтому я выяснил ответ долгое время после того, как это было спрошено, но на всякий случай кто-то этого захочет, я подумал, что было бы разумно идти дальше и публиковать ответ.
В принципе, это невозможно сделать с помощью диалогового окна Alert Dialog, это связано с поведением при нажатии кнопки и отрицательных кнопок. Однако это можно сделать с помощью обычного диалога. Вам нужно несколько анимационных xmls, и их можно найти в папке api demo anim под res (исходный java файл - Animation1.java в api demos, чтобы вы могли проверить это). Я также сделал так, чтобы клавиатура была готова для ввода пользователем. Вы можете избавиться от этого, удалив все элементы inputmanager. В любом случае здесь код в диалоговом окне.
public void showAgeDialog() {
final Dialog dialog = new Dialog(Information.this);
dialog.setContentView(R.layout.age_dialog);
dialog.setTitle(R.string.InputAge);
final EditText ageEditText = (EditText) dialog.findViewById(R.id.AgeEditText);
inputManager.toggleSoftInput(InputMethodManager.SHOW_FORCED, InputMethodManager.HIDE_IMPLICIT_ONLY);
dialog.show();
Button positive = (Button) dialog.findViewById(R.id.OkButton);
Button negative = (Button) dialog.findViewById(R.id.CancelButton);
positive.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
if (ageEditText.getText().toString().isEmpty()) {
Animation shake = AnimationUtils.loadAnimation(Information.this, R.anim.shake);
ageEditText.startAnimation(shake);
Toast.makeText(Information.this, "Please enter an age", Toast.LENGTH_SHORT).show();
}
else {
database.updateAge(Integer.parseInt(ageEditText.getText().toString()));
inputManager.hideSoftInputFromWindow(ageEditText.getWindowToken(), 0);
dialog.dismiss();
}
}
});
negative.setOnClickListener(new Button.OnClickListener() {
public void onClick(View v) {
inputManager.hideSoftInputFromWindow(ageEditText.getWindowToken(), 0);
dialog.dismiss();
}
});
}
Вот код моего макета. Я сделал это диалоговое окно таким же, как диалоговое окно Alert Dialog с кнопками Ok и Cancel вместе с серым фоном.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >
<EditText
android:id="@+id/AgeEditText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginBottom="18dp"
android:layout_marginLeft="100dp"
android:layout_marginRight="100dp"
android:hint="@string/Years"
android:inputType="number"
android:maxLength="2"
android:textSize="18sp" >
</EditText>
<LinearLayout
style="@android:style/ButtonBar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<Button
android:id="@+id/OkButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/Ok" />
<Button
android:id="@+id/CancelButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/Cancel" />
</LinearLayout>
</LinearLayout>
Немного истории о любви летом:
Если вы хотите встряхнуть весь AlertDialog
, а не только EditText
, вы можете сделать что-то подобное в своем фрагменте диалога:
(ЗАМЕЧАНИЕ! Для ясности я не использовал никаких проверок здравомыслия, таких как нулевая проверка в контексте и окне в примере кода)
public Dialog onCreateDialog(Bundle savedInstanceState) {
// Create the alert dialog as usual.
AlertDialog shakyAlertDialog = new AlertDialog.Builder(getContext())
.setTitle(R.string.title)
.setMessage(R.string.message) // Optional
.setView(R.layout.input) // This one holds your EditText
.setNegativeButton(R.string.cancel, null)
.setPositiveButton(R.string.ok, null)
.show();
// Get hold of the edit text we want to validate on.
EditText input = shakyAlertDialog.findViewById(R.id.age_input);
// Replace the "OK" button click listener. As discussed in previous
// answers this will replace the auto-dismiss behavior.
shakyAlertDialog
.getButton(DialogInterface.BUTTON_POSITIVE)
.setOnClickListener(view -> {
if (input.getText().isEmpty()) {
// This is the gold. This is how we shake the entire
// AlertDialog, not only the EditText.
shakyAlertDialog
.getWindow()
.getDecorView()
.animate()
.translationX(16f)
.setInterpolator(new CycleInterpolator(7f))
} else {
// Do something with the input, but don't
// forget to manually dismiss the dialog.
shakyAlertDialog.dismiss()
}
});
return shakyAlertDialog;
}
Окончательно можно реализовать запрос OPs с помощью AlertDialog. Тем не менее, нужно немного подкорректировать.
AlertDialog
зарегистрирует свой собственный OnClickListener
на кнопках, которые вы создаете вместе с построителем. Эти обработчики передадут ваш зарегистрированный слушатель перед тем, как отклонить диалог.
Решение обходить это поведение по умолчанию - зарегистрировать свой собственный обработчик сразу после вызова show()
и тем самым переопределить диалоговые собственные слушатели:
mLayout = mInflater.inflate(R.layout.agedialog, null);
mAgeEditText = (EditText) mLayout.findViewById(R.id.AgeEditText);
mAgeResultTextView = (TextView) findViewById(R.id.AgeResultTextView);
Animation shake = AnimationUtils.loadAnimation(Information.this, R.anim.shake);
// create dialog with buttons but without registering click listeners
AlertDialog dialog = new AlertDialog.Builder(Information.this)
.setView(mLayout)
.setTitle(R.string.EnterYourAge)
.setPositiveButton(R.string.OK, null) // only declare button, add listener later
.setNegativeButton(R.string.Cancel, null) // dito
.create();
// define click listeners for ok and cancel
OnClickListener okListener = new OnClickListener() {
public void onClick(View button) {
mInputManager.hideSoftInputFromWindow(mAgeEditText.getWindowToken(), 0);
if (TextUtils.isEmpty(mAgeEditText.getText())) {
// input not valid -> shake
mAgeEditText.startAnimation(shake);
}
else {
HelperClass.getInstance().setAge(Integer.parseInt(mAgeEditText.getText().toString()));
mAgeResultTextView.setText(HelperClass.getInstance().getAge());
dialog.dismiss(); // close dialog, since input is valid
}
}
};
OnClickListener cancelListener = ...
// show dialog and immediately register our own listeners afterwards
dialog.show();
dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(okListener);
dialog.getButton(AlertDialog.BUTTON_NEGATIVE).setOnClickListener(cancelListener);
Отвечайте на мой ответ Android: диалог отклоняется, не вызывая отклонения, чтобы не отклонять диалог.