如何在Android上重复使用AlertDialog for Yes / No?

时间:2013-08-24 01:06:43

标签: android alertdialog reusability

我正在尝试找到重用显示自定义标题的Dialog的方法,然后将Yes / No click发送到已启动Dialog的函数。

我有两个按钮,保存和解除,并且都会调用是/否对话,一个显示“你想要保存”,另一个显示“解除更改吗?”。

我认为我的程序非常“脏”但我想它可以工作,但我的问题是“查看视图”变量,我不知道如何将它从Activity传递给Dialog,所以我可以使用它回顾了启动Dialog的功能。

提前致谢, HerniHdez

.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");
    }
}
}

2 个答案:

答案 0 :(得分:5)

由于此页面是Google上的第一个热门话题,并且看起来像是一个很常见的任务而且关于它的文章很少,我将分享我发现的可重用DialogFragment的方式。

如果要从同一个类多次重复使用相同的Dialog,但是每次执行不同的操作时,使用接口会变得非常混乱。这个解决方案是一种简单而直接的方法来解决这个问题而不会带来任何不利之处。

编辑2017-02-25: 此答案以前使用Abstract类来实现confirm()和cancel(),但是如果您尝试将匿名类用作DialogFragment,则新版本的Android将崩溃并出现以下错误:

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,你可以使用lambdas作为使代码更简洁的函数。有关示例,请参阅here

答案 1 :(得分:4)

完整解决方案试试这个

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

                    }
                });