【问题标题】:How can I reuse an AlertDialog for Yes/No on Android?如何在 Android 上为 Yes/No 重复使用 AlertDialog?
【发布时间】:2013-08-24 01:06:43
【问题描述】:

我正在尝试找到重用显示自定义标题的对话框的方法,然后将“是/否”单击发送到已启动该对话框的功能。

我有两个按钮,Save 和 Dismiss,都调用 Yes/No Dialog,一个显示“Do you want to save”,另一个显示“Dismiss changes?”。

我认为我的程序很“脏”但我想它可以工作,但我的问题是“视图视图”变量,我不知道如何将它从 Activity 传递给 Dialog,所以我可以使用它来调用启动对话框的函数。

提前致谢, 赫尼赫德兹

.java 我的活动(片段)

public void open_HH_Fragment_YesNo(View view, String aux_title, String aux_function)
{
    Bundle bundle=new Bundle();
    bundle.putString("setMessage", aux_title);
    bundle.putString("callingFunction", aux_function);

    DialogFragment newFragment = new HH_Fragment_YesNo();
    newFragment.setArguments(bundle);
    newFragment.show(getSupportFragmentManager(), "HH_Fragment_YesNo");
}

public void SaveChanges(View view, String aux_YesNo)
{
    if (aux_YesNo == "")
    {
        Toast.makeText(this, "Save changes?", Toast.LENGTH_SHORT).show();
        open_HH_Fragment_YesNo(view, "Save changes?", "SaveChanges");
    }
    else if (aux_YesNo == "Yes")
    {
        Toast.makeText(this, "Saving changes", Toast.LENGTH_SHORT).show();
    }
    else if (aux_YesNo == "No")
    {
        Toast.makeText(this, "Save Cancelled", Toast.LENGTH_SHORT).show();
    }
}

public void DismissChanges(View view, String aux_YesNo)
{
    if (aux_YesNo == "")
    {
        Toast.makeText(this, "Dismiss changes?", Toast.LENGTH_SHORT).show();
        open_HH_Fragment_YesNo(view, "Dismiss changes?", "DismissChanges");
    }
    else if (aux_YesNo == "Yes")
    {
        Toast.makeText(this, "Dismiss OK", Toast.LENGTH_SHORT).show();
        Close(view);
    }
    else if (aux_YesNo == "No")
    {
        Toast.makeText(this, "Dismiss Cancelled", Toast.LENGTH_SHORT).show();
    }
}

// The dialog fragment receives a reference to this Activity through the
// Fragment.onAttach() callback, which it uses to call the following methods
// defined by the HH_Fragment_YesNo.YesNoDialogListener interface
@Override
public void onDialogPositiveClick(DialogFragment dialog, View view, String aux_function)
{
    // User touched the dialog's positive button
    Toast.makeText(this, "User clicked on Yes", Toast.LENGTH_SHORT).show();

    if (aux_function == "SaveChanges")
    {
        SaveChanges(view, "Yes");
    }
    else if (aux_function == "DismissChanges")
    {
        DismissChanges(view, "Yes");
    }
}

@Override
public void onDialogNegativeClick(DialogFragment dialog, View view, String aux_function)
{
    Toast.makeText(this, "User clicked on NO", Toast.LENGTH_SHORT).show();

    if (aux_function == "SaveChanges")
    {
        SaveChanges(view, "No");
    }
    else if (aux_function == "DismissChanges")
    {
        DismissChanges(view, "No");
    }
}

我的对话框的.java(完整)

public class HH_Fragment_YesNo extends DialogFragment
{
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState)
    {
    // Use the Builder class for convenient dialog construction
    AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    String setMessage = getArguments().getString("setMessage");
    final String callingFunction = getArguments().getString("callingFuntion");

    builder
        .setMessage(setMessage)                                             // R.string.dialog_fire_missiles
        .setPositiveButton("Sí", new DialogInterface.OnClickListener()      // R.string.fire
        {
            public void onClick(DialogInterface dialog, int id)
            {
                // Exit without saving
                mListener.onDialogPositiveClick(HH_Fragment_YesNo.this, view, callingFunction);
            }
        })
        .setNegativeButton("No", new DialogInterface.OnClickListener()      // R.string.cancel
        {
            public void onClick(DialogInterface dialog, int id)
            {
                // User cancelled the dialog
                mListener.onDialogNegativeClick(HH_Fragment_YesNo.this, view, callingFunction);
            }
        });

    // Create the AlertDialog object and return it
    return builder.create();
}


/* The activity that creates an instance of this dialog fragment must
 * implement this interface in order to receive event callbacks.
 * Each method passes the DialogFragment in case the host needs to query it. */
public interface YesNoDialogListener
{
    public void onDialogPositiveClick(DialogFragment dialog, View view, String aux_Function);
    public void onDialogNegativeClick(DialogFragment dialog, View view, String aux_Function);
}


// Use this instance of the interface to deliver action events
YesNoDialogListener mListener;


// Override the Fragment.onAttach() method to instantiate the NoticeDialogListener
@Override
public void onAttach(Activity activity)
{
    super.onAttach(activity);
    // Verify that the host activity implements the callback interface
    try
    {
        // Instantiate the NoticeDialogListener so we can send events to the host
        mListener = (YesNoDialogListener) activity;
    }
    catch (ClassCastException e)
    {
        // The activity doesn't implement the interface, throw exception
        throw new ClassCastException(activity.toString() + " must implement NoticeDialogListener");
    }
}
}

【问题讨论】:

    标签: android android-alertdialog reusability


    【解决方案1】:

    完整的解决方案试试这个

    1) 创建界面

    import android.content.DialogInterface;
    
    public interface AlertMagnatic {
    
        public abstract void PositiveMethod(DialogInterface dialog, int id);
        public abstract void NegativeMethod(DialogInterface dialog, int id);
    }
    

    2) 确认对话框的泛化方法。

    public static void getConfirmDialog(Context mContext,String title, String msg, String positiveBtnCaption, String negativeBtnCaption, boolean isCancelable, final AlertMagnatic target) {
            AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
    
            int imageResource = android.R.drawable.ic_dialog_alert;
            Drawable image = mContext.getResources().getDrawable(imageResource);
    
            builder.setTitle(title).setMessage(msg).setIcon(image).setCancelable(false).setPositiveButton(positiveBtnCaption, new DialogInterface.OnClickListener() {
                public void onClick(DialogInterface dialog, int id) {
                    target.PositiveMethod(dialog, id);
                }
            }).setNegativeButton(negativeBtnCaption, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int id) {
                    target.NegativeMethod(dialog, id);
                }
            });
    
            AlertDialog alert = builder.create();
            alert.setCancelable(isCancelable);
            alert.show();
            if (isCancelable) {
                alert.setOnCancelListener(new OnCancelListener() {
    
                    @Override
                    public void onCancel(DialogInterface arg0) {
                        target.NegativeMethod(null, 0);
                    }
                });
            }
        }
    

    3) 使用方法

    getConfirmDialog(getString(R.string.logout), getString(R.string.logout_message), getString(R.string.yes), getString(R.string.no), false,
                    new AlertMagnatic() {
    
                        @Override
                        public void PositiveMethod(final DialogInterface dialog, final int id) {}
    
                        @Override
                        public void NegativeMethod(DialogInterface dialog, int id) {
    
                        }
                    });
    

    【讨论】:

    • 感谢 Biraj,我不确定我必须将代码的每个部分放在哪里。 * 接口是在不同的文件中还是在 Activity 的 java 文件中?
    • 我建议把它作为单独的文件放在你的包中。
    • 我猜“确认对话框的通用方法”在Dialog的java文件中,而“如何使用”在activity文件中,对吧?
    • 变量“id”的作用是什么?如何从我的 xml 调用 Dialog 以传递所有参数? (android:onClick="SaveChanges")
    • 不要使用 android:onClick="SaveChanges" 属性,因为它将支持 android 版本
    【解决方案2】:

    由于此页面是 Google 上的第一个热门页面,而且它似乎是一项如此常见的任务,但很少有人提及它,所以我将分享我发现的展示可重复使用的 DialogFragment 的方式。

    如果您想从同一个类中多次重用同一个对话框,但每次都执行不同的操作,那么使用接口会变得非常混乱。此解决方案是解决该问题的一种简单直接的方法,不会带来任何缺点。

    编辑 2017-02-25: 此答案之前使用抽象类来实现确认()和取消(),但是如果您尝试将匿名类用作 DialogFragment,较新版本的 Android 将崩溃并出现以下错误: p>

    java.lang.IllegalStateException: Fragment null must be a public static class to be properly recreated from instance state.

    所以我修改了使用 Runnables 的解决方案,它在 Java8 中非常好用,但没有它也可行

    首先,创建一个实现Dialog本身创建的类:

    /**
     * This is a reusable convenience class which makes it easy to show a confirmation dialog as a DialogFragment.
     * Create a new instance, call setArgs(...), setConfirm(), and setCancel() then show it via the fragment manager as usual.
     */
    public class ConfirmationDialog extends DialogFragment {
        // Do nothing by default
        private Runnable mConfirm = new Runnable() {
            @Override
            public void run() {
            }
        };
        // Do nothing by default
        private Runnable mCancel = new Runnable() {
            @Override
            public void run() {
            }
        };
    
        public void setArgs(String message) {
            setArgs("" , message);
        }
    
        public void setArgs(String title, String message) {
            Bundle args = new Bundle();
            args.putString("message", message);
            args.putString("title", title);
            setArguments(args);
        }
    
        public void setConfirm(Runnable confirm) {
            mConfirm = confirm;
        }
    
        public void setCancel(Runnable cancel) {
            mCancel = cancel;
        }
    
        @Override
        public MaterialDialog onCreateDialog(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            Resources res = getActivity().getResources();
            String title = getArguments().getString("title");
            return new MaterialDialog.Builder(getActivity())
                    .title(title.equals("") ? res.getString(R.string.app_name) : title)
                    .content(getArguments().getString("message"))
                    .positiveText(res.getString(R.string.dialog_ok))
                    .negativeText(res.getString(R.string.dialog_cancel))
                    .callback(new MaterialDialog.ButtonCallback() {
                        @Override
                        public void onPositive(MaterialDialog dialog) {
                            mConfirm.run();
                        }
    
                        @Override
                        public void onNegative(MaterialDialog dialog) {
                            mCancel.run();
                        }
                    })
                    .show();
        }
    }
    

    其次,您应该在您的Activity 中创建一个通用方法,使用片段管理器显示DialogFragment

    /**
     * Global method to show dialog fragment
     * @param newFragment  the DialogFragment you want to show
     */
    public void showDialogFragment(DialogFragment newFragment) {
        // DialogFragment.show() will take care of adding the fragment
        // in a transaction. We also want to remove any currently showing
        // dialog, so make our own transaction and take care of that here.
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        Fragment prev = getSupportFragmentManager().findFragmentByTag("dialog");
        if (prev != null) {
            ft.remove(prev);
        }
        // save transaction to the back stack
        ft.addToBackStack("dialog");
        newFragment.show(ft, "dialog");
    }
    

    然后您可以在Activity 中的任何位置显示一个确认对话框,如下所示:

    ConfirmationDialog dialog = new ConfirmationDialog ();
    dialog.setArgs(stringDialogTitle, stringDialogMessage);
    Runnable confirm = new Runnable() {
        @Override
        public void run() {
            doStuff();
        }
    };
    dialog.setConfirm(confirm);
    showDialogFragment(dialog);
    

    如果你有 Java8,你可以对函数使用 lambda,这将使代码不那么冗长。示例见here

    【讨论】:

      猜你喜欢
      • 2020-06-23
      • 2016-11-06
      • 2018-10-09
      • 1970-01-01
      • 1970-01-01
      • 2020-04-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多