【问题标题】:Simplest yes/no dialog fragment最简单的是/否对话框片段
【发布时间】:2012-10-06 09:42:11
【问题描述】:

我想创建一个dialog fragment,询问“你确定吗?”回复“是/否”。

我看过the documentation,它真的很冗长,到处都是,解释如何制作高级对话框,但没有完整的代码来制作简单的“hello world”类型的对话框。大多数教程使用已弃用的对话框系统。 official blog 似乎过于复杂且难以理解。

那么,创建和显示一个非常基本的警报对话框的最简单方法是什么?使用支持库的奖励积分。

【问题讨论】:

标签: android dialog android-fragments android-alertdialog


【解决方案1】:

那么,创建和显示一个非常基本的警报的最简单方法是什么 对话?使用支持库的奖励积分。

只需创建一个DialogFragment(SDK 或支持库)并覆盖其onCreateDialog 方法以返回一个带有所需文本和按钮的AlertDialog

public static class SimpleDialog extends DialogFragment {

    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        return new AlertDialog.Builder(getActivity())
                .setMessage("Are you sure?")
                .setPositiveButton("Ok", null)
                .setNegativeButton("No way", null)
                .create();
    }

}

要在用户使用其中一个按钮时执行某些操作,您必须提供 DialogInterface.OnClickListener 的实例,而不是我的代码中的 null 引用。

【讨论】:

    【解决方案2】:

    DialogFragment 实际上只是一个包装对话框的片段。您可以通过在 DialogFragment 的 onCreateDialog() 方法中创建并返回对话框来将任何类型的对话框放入其中。

    这是一个示例 DialogFragment:

    class MyDialogFragment extends DialogFragment{
        Context mContext;
        public MyDialogFragment() {
            mContext = getActivity();
        }
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(mContext);
            alertDialogBuilder.setTitle("Really?");
            alertDialogBuilder.setMessage("Are you sure?");
            //null should be your on click listener
            alertDialogBuilder.setPositiveButton("OK", null);
            alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
    
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
    
    
            return alertDialogBuilder.create();
        }
    }
    

    创建对话调用:

    new MyDialogFragment().show(getFragmentManager(), "MyDialog");
    

    并从某处关闭对话框:

    ((MyDialogFragment)getFragmentManager().findFragmentByTag("MyDialog")).getDialog().dismiss();
    

    只需更改导入以使用支持库类,所有这些代码都将与支持库完美配合。

    【讨论】:

    • 谢谢,但如果我在对话框打开时退出并重新进入应用程序,似乎会导致错误Unable to instantiate fragment: make sure class name exists, is public, and has an empty constructor that is public。添加了一个空构造函数,但随后在 mContext 上获得了一个空指针。
    • @muz Android 系统要求Fragment 类有一个无参数的构造函数,以便在需要时实例化片段。在Fragment 中,您可以引用通过getActivity() 方法使用此片段的活动(使用它而不是mContext)。此外,该片段必须在其自己的 java 文件中声明,或在另一个类中声明为 inner static 类。否则 Android 将无法找到您的片段来实例化它。
    • 是的,抱歉,我在发布 mContext 和构造函数后意识到实际上并不需要。虽然在我测试时它运行良好,但我在内部静态类中有 FragmentDialog。
    • 我认为你必须调用fragment的dismiss()方法而不是dialog。
    【解决方案3】:

    因为 Activity / Fragment 生命周期 @athor & @lugsprog 方法可能会失败, 更优雅的方法是**从方法 onAttach 获取活动上下文并将其存储为弱引用**(并尽量避免 DialogFragment 中的非默认构造函数!,将任何参数传递给对话框使用参数),如下所示:

    public class NotReadyDialogFragment extends DialogFragment {
    
        public static String DIALOG_ARGUMENTS = "not_ready_dialog_fragment_arguments";
    
        private WeakReference<Context> _contextRef;
    
        public NotReadyDialogFragment() {
        }
    
        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
    
            /** example pulling of arguments */
            Bundle bundle = getArguments();
            if (bundle!=null) {
                bundle.get(DIALOG_ARGUMENTS);
            }
    
            //
            // Caution !!!
            // check we can use contex - by call to isAttached 
            // or by checking stored weak reference value itself is not null 
            // or stored in context -> example allowCreateDialog() 
            // - then for example you could throw illegal state exception or return null 
            //
            AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(_contextRef.get());
            alertDialogBuilder.setMessage("...");
            alertDialogBuilder.setNegativeButton("Przerwij", new DialogInterface.OnClickListener() {
    
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    dialog.dismiss();
                }
            });
            return alertDialogBuilder.create();
        }
    
        @Override
        public void onAttach(Activity activity) {
            super.onAttach(activity);
            _contextRef = new WeakReference<Context>(activity);
        }
    
         boolean allowCreateDialog() {
             return _contextRef !== null 
                    && _contextRef.get() != null;
         }
    

    编辑: & 如果你想关闭对话框,那么:

    1. 尝试得到它
    2. 检查是否存在
    3. 检查是否显示
    4. 解雇

    类似这样的:

            NotReadyDialogFragment dialog = ((NotReadyDialogFragment) getActivity().getFragmentManager().findFragmentByTag("MyDialogTag"));
        if (dialog != null) {
            Dialog df = dialog.getDialog();
            if (df != null && df.isShowing()) {
                df.dismiss();
            }
        }
    

    EDIT2: & 如果你想将对话框设置为不可取消,你应该像这样更改 onCreatweDialog 返回语句:

        /** convert builder to dialog */
        AlertDialog alert = alertDialogBuilder.create();
        /** disable cancel outside touch */
        alert.setCanceledOnTouchOutside(false);
        /** disable cancel on press back button */
        setCancelable(false);
    
        return alert;
    

    【讨论】:

    • 所以我知道在构造函数中调用getActivity()可能会失败,但是为什么Luksprog建议的解决方案会失败呢?在onCreateDialog() 中调用getActivity() 正是默认实现所做的,存储我自己对上下文的引用听起来与我想做的相反。
    • @Thorbear getActivity() 可能在片段未附加到活动时返回 null - 您可以使用它,但您应该检查它 - 例如在片段中使用 getResources() 而片段未附加跨度>
    • 是的,通常(总是)在调用构造函数时不附加片段。但是在没有附加片段的情况下会调用onCreateDialog() 吗?同样,默认实现(支持库)在 onCreateDialog() 中调用 getActivity() 而不检查 null,您是说应该这样做吗?
    【解决方案4】:

    对于那些使用 Kotlin 和 Anko 编码的人,您现在可以用 4 行代码进行对话:

    alert("Order", "Do you want to order this item?") {
        positiveButton("Yes") { processAnOrder() }
        negativeButton("No") { }
    }.show()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多