问题
So I have a dialog in which the user inputs data, here it is the user's age. So I would like that when/if the user leaves the edittext blank, the edittext will do the shake animation like that in the api demos. So far I cannot get the dialog from not dismissing when invalid info is inputed. Thanks.
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();
回答1:
Ok so I figured out the answer a long time after this was asked but just in case someone wants this I thought it was wise to go ahead and post the answer.
Basically this can NOT be done with the Alert Dialog, it has to do with the behavior when the button and negative buttons are clicked. However it can be done with a regular Dialog. You need a few animation xmls, and those can be found in the api demo's anim folder under res (The original java file is Animation1.java in api demos so you can check that out). I also made it so that the keyboard comes up ready for the user to type. You can rid of that by deleting all the inputmanager stuff. Anyway here's the code to the dialog.
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();
}
});
}
Here is the code to my layout. I made this dialog look exactly like an Alert Dialog with the Ok and Cancel buttons along with the gray background.
<?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>
回答2:
An extra little summer love story:
If you want to shake the entire AlertDialog
, not only the EditText
you can do something like this in your dialog fragment:
(NOTE! I have, for the sake of clarity, omitted any sanity checks, like null validation on context's and window's in the example code)
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's 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;
}
回答3:
It is definitively possible to implement OPs request with AlertDialog. A bit of tweaking is necessary, though.
AlertDialog
will register its own OnClickListener
on the buttons you create with the builder. Those handlers will delegate to your registered listener before dismissing the dialog.
The solution to circumvent this default behavior is to register your own handler immediately after the call to show()
and thereby override the dialog's own listeners:
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);
来源:https://stackoverflow.com/questions/5577608/shake-animation-with-alert-dialog-if-invalid-info-shake-the-edittext-do-not-d