AlertDialog、PopupWindow 与 Activity 之间区别

本文探讨如何使用AlertDialog和PopupWindow实现对话框,并详细解析它们与Activity之间的区别。PopupWindow是一个悬浮窗口,能显示任意布局,而AlertDialog是Dialog的子类,常用于弹出对话。关键区别在于:AlertDialog弹出时后台仍可执行,PopupWindow则会阻塞程序,直至调用dismiss方法。此外,PopupWindow直接将View添加到DecorView,Dialog则新建一个window。

1、使用 AlertDialog 和 PopupWindow 实现对话

1.1 使用 PopupWindow 实现自定义对话框

PopupWindow 就是一个悬浮在 Activity 之上的窗口,可以用展示任意布局文件。PopupWindow 是在 Android 上实现自定义对话框的众多方式之一。下面是它用来实现对话框的一个示例:

我们想要实现的效果如下所示:
UI效果

如果我们使用Android的PopDialog的话实现这种效果会比较繁琐,我们可以通过自定义对话框解决这个问题:

public class PopDialogController {

    public static void showSortDialog(Activity activity, View view, OnMenuItemSelectedListener onMenuItemSelectedListener) {
        // 这里我们使用PopupWindow来达到上述效果
        PopupWindow popDialog = new PopupWindow();

        // 一个枚举,用来指定默认的选项
        SortField sortField = SortField.fromValue(PersistData.getInteger(Constants.KEY_SORT_FIELD, SortField.CreateDate.value));

        // 加载布局文件
        View root = LayoutInflater.from(activity).inflate(R.layout.dialog_pop_sort, null, false);
        // 设置按钮的单击事件并进行回调
        root.findViewById(R.id.ll_receipt_date).setOnClickListener(v -> {
            if (onMenuItemSelectedListener != null) {
                onMenuItemSelectedListener.onReceiptDate(popDialog);
            }
        });
        root.findViewById(R.id.ll_shot_date).setOnClickListener(v -> {
            if (onMenuItemSelectedListener != null) {
                onMenuItemSelectedListener.onShotDate(popDialog);
            }
        });

        // 设置用于显示的图片控件
        int drawableRes = sortField == SortField.CreateDate ? R.drawable.icon_kaipiao : R.drawable.icon_paizhao;
        Drawable drawable = ColorUtils.tintDrawable(PalmUtils.getDrawableCompact(drawableRes),
                PalmUtils.getColorCompact(R.color.gray));
        ImageView imageView = root.findViewById(sortField == SortField.CreateDate ? R.id.iv_create : R.id.iv_shot);
        imageView.setImageDrawable(drawable);

        // 设置文字颜色
        TextView textView = root.findViewById(sortField == SortField.CreateDate ? R.id.tv_create : R.id.tv_shot);
        textView.setTextColor(PalmUtils.getColorCompact(R.color.gray));

        // 测量文字,为了UI对齐效果,获取对话框的宽度
        Paint paint = new Paint();
        float txtWidth = paint.measureText(PalmUtils.getStringCompact(R.string.sort_type_shot_date));
        int width = ViewUtils.dp2Px(activity, 70 + txtWidth);

        // 设置View到对话框上面
        popDialog.setContentView(root);
        popDialog.setBackgroundDrawable(new ColorDrawable(0));
        // 设置当弹出对话框的有一层灰色蒙版
        backgroundAlpha(activity,0.5f);
        popDialog.setWidth(width);
        popDialog.setHeight(ViewUtils.dp2Px(activity, 80));
        popDialog.setFocusable(true);
        // 设置对话框相对于指定控件的位置
        popDialog.showAsDropDown(view, ViewUtils.dp2Px(activity, 30) - width, 0);
        // 设置对话框消失之后的效果
        popDialog.setOnDismissListener(() -> backgroundAlpha(activity, 1f));
        popDialog.update();
    }

    private static void backgroundAlpha(Activity context, float bgAlpha) {
        WindowManager.LayoutParams lp = context.getWindow().getAttributes();
        lp.alpha = bgAlpha;
        context.getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
        context.getWindow().setAttributes(lp);
    }

    public interface OnMenuItemSelectedListener {
        void onShotDate(PopupWindow dialog);
        void onReceiptDate(PopupWindow dialog);
    }
}

1.2 使用 AlertDialog 实现对话框

AlertDialog 是 Dialog 的子类,所以它包含了 Dialog 类的很多属性和方法。是弹出对话框的主要方式,对话框分成支持包的和非支持包的,UI 效果上略有区别。因为它使用比较频繁,这里我们就不贴出其代码了。

2、AlertDialog、PopupWindow 与 Activity 之间区别

对于 AlertDialog 与 PopupWindow,它们之间在实现对话框的时候有些许的区别,这里我们总结了,因为大部分属于 UI 上的区别。

AlertDialog 与 PopupWindow 之间最本质的差异在于

  1. AlertDialog 是非阻塞式对话框;而PopupWindow 是阻塞式对话框。AlertDialog 弹出时,后台还可以做事情;PopupWindow 弹出时,程序会等待,在PopupWindow 退出前,程序一直等待,只有当我们调用了 dismiss() 方法的后,PopupWindow 退出,程序才会向下执行。我们在写程序的过程中可以根据自己的需要选择使用 Popupwindow 或者是 Dialog.
  2. 两者最根本的区别在于有没有新建一个 window,PopupWindow 没有新建,而是通过 WMS 将 View 加到 DecorView;Dialog 是新建了一个 window (PhoneWindow),相当于走了一遍 Activity 中创建 window 的流程。

(详情自行阅读源码即可,两者的源码并不复杂)

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值