Android 推荐的自定义 Dialog 实现方式

本文探讨了Android中推荐的自定义Dialog实现方式,重点介绍了使用DialogFragment的原因和优势,包括处理旋转和内存泄露问题。内容涵盖重写onCreateView()、键盘弹出时Dialog的适配、Dialog宽度设置以及使用AlertDialog的场景。同时,还讲解了Dialog位置和背景的调整方法。

原因

官方推荐的方式是使用AlertDialog,DialogFragment来实现。虽然说很多网上的例子直接使用了extends Dialog来实现,但大部分时间我们应该使用上述的两种方式,因为有时候没有考虑到旋转或者Activity到后台后,Dialog附在的Activity消失,引起内存泄露的问题。

国内很多应用喜欢用Dialog的方式,基本上很大程度上要自定义Dialog中的button,这时候用DialogFragment其实可以实现,而且实现上也比较方便。

如同官方Dialog 类是对话框的基类,但您应该避免直接实例化 Dialog,而是使用下列子类之一:说的这样,我们应该使用extends类。

实现方式

其实主要讲解是DialogFragment,主要是国内的应用还是在仿IOS,少有遵循Material Design的设计,所以Button也是需要自定义的,那么AlertDialog就无法满足需要。这里引用官方的一段描述。

这些类定义您的对话框的样式和结构,但您应该将 DialogFragment 用作对话框的容器。DialogFragment 类提供您创建对话框和管理其外观所需的所有控件,而不是调用 Dialog 对象上的方法。

使用 DialogFragment 管理对话框可确保它能正确处理生命周期事件,如用户按“返回”按钮或旋转屏幕时。 此外,DialogFragment 类还允许您将对话框的 UI 作为嵌入式组件在较大 UI 中重复使用,就像传统 Fragment 一样(例如,当您想让对话框 UI 在大屏幕和小屏幕上具有不同外观时)。

重写onCreateView()

@Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        View inflate = inflater.inflate(R.layout.fragment_edit_name, container, false);
        mEditText = (EditText) inflate.findViewById(R.id.txt_your_name);
        mButton1 = (Button) inflate.findViewById(R.id.btn1);
        mButton2 = (Button) inflate.findViewById(R.id.btn2);
        return inflate;
    } 

这样基本就完成了,什么样式都在于你自己去实现。

设置有输入的Dialog调整,当键盘弹出

希望键盘可以说弹出,并且不挡住取消和确定这类的Button时,可以在onactivityCreated()中设置,其它地方也可以说。

@Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
    }

其中SOFT_INPUT_STATE_*中的各类型见名知意,这样了弹出直接拉起键盘,对用户也十分方便。更具体的使用请参考官方的DialogFragment

如下图所示为弹出和键盘自动弹出的情况,然后收缩键盘的情况。

如果说显示的内容特别多还是会把下面的给遮挡住的。下面这张图的情况就是过长的内容并不会把内容往上移动,因为移动已经超出屏幕了。

关于宽度设置为match_parent时不占全的解决办法

在一些情况下有这种要求,处理很容易在onStart()中把背景色处理一下就可以了,也有说传null,但我认为下面方式更好些。

  @Override
    public void onStart() {
        super.onStart();
        getDialog().getWindow().setBackgroundDrawable(new ColorDrawable(android.graphics.Color.TRANSPARENT));
    }

使用AlertDialog方式实现

这个时候不需要实现onCreateView(),这时应该实现public Dialog onCreateDialog(Bundle savedInstanceState),如下代码所示。

@NonNull
    @Override
    public Dialog onCreateDialog(Bundle savedInstanceState) {
        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
        // Get the layout inflater
        LayoutInflater inflater = getActivity().getLayoutInflater();

        // Inflate and set the layout for the dialog
        // Pass null as the parent view because its going in the dialog layout
        View inflate = inflater.inflate(R.layout.dialog_test, null);
        mEditText = (EditText) inflate.findViewById(R.id.editText);
        mEditTest2 = (EditText) inflate.findViewById(R.id.editText2);




        builder.setView(inflate)
                // Add action buttons
                .setPositiveButton("确定", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int id) {
                        // sign in the user ...
                    }
                })
                .setNegativeButton("取消", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        TestDialog.this.getDialog().cancel();
                    }
                });
        return builder.create();

    }

如果之后需要request focus,应该在onActivityCreated()里面写。

    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        mEditText.requestFocus();
        getDialog().setTitle("haha");
        getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
    }

关于Dialog位置和背景的设置

需要设置时需要
得到顶层的window,可以参考下面的代码段1代码段2

Dialog dlg = <code to create custom dialog>;

Window window = dlg.getWindow();
WindowManager.LayoutParams wlp = window.getAttributes();

wlp.gravity = Gravity.BOTTOM;
wlp.flags &= ~WindowManager.LayoutParams.FLAG_DIM_BEHIND;
window.setAttributes(wlp);
private CharSequence[] items = {"Set as Ringtone", "Set as Alarm"};
    AlertDialog.Builder builder = new AlertDialog.Builder(this);
    builder.setItems(items, new DialogInterface.OnClickListener() { 
        public void onClick(DialogInterface dialog, int item) {

            if(item == 0) {

            } else if(item == 1) {

            } else if(item == 2) {

            } 
        } 
    }); 

     AlertDialog dialog = builder.create();
     dialog.requestWindowFeature(Window.FEATURE_NO_TITLE); 
     WindowManager.LayoutParams wmlp = dialog.getWindow().getAttributes();

 wmlp.gravity = Gravity.TOP | Gravity.LEFT; 
 wmlp.x = 100;   //x position 
 wmlp.y = 100;   //y position 

 dialog.show(); 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值