使用警报对话框摇动动画(如果无效信息,请摇动编辑文本并不要关闭)



所以我有一个用户输入数据的对话框,这里是用户的年龄。所以我希望当/如果用户让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();

一个额外的夏日小爱情故事:

如果你想摇动整个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'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;
}

好的,所以我想出了答案很长一段时间后,这是问,但万一有人想要这个,我认为这是明智的继续并发布答案。

基本上这不能用警告对话框完成,它与按钮和消极按钮被点击时的行为有关。然而,这可以用一个常规的对话框来完成。你需要一些动画xml文件,这些文件可以在api demo的animm文件夹res下找到(api demo中的原始java文件是Animation1.java,所以你可以查看一下)。我还做了这样的设计,这样键盘就可以让用户随时输入。你可以通过删除所有的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();
        }
    });
}

这是我的布局代码。我让这个对话框看起来完全像一个警告对话框,有确定和取消按钮,背景是灰色的。

    <?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实现OPs请求是完全可能的。不过,稍微调整一下是必要的。

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

最新更新