1、使用 AlertDialog 和 PopupWindow 实现对话
1.1 使用 PopupWindow 实现自定义对话框
PopupWindow 就是一个悬浮在 Activity 之上的窗口,可以用展示任意布局文件。PopupWindow 是在 Android 上实现自定义对话框的众多方式之一。下面是它用来实现对话框的一个示例:
我们想要实现的效果如下所示:

如果我们使用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 之间最本质的差异在于:
AlertDialog 是非阻塞式对话框;而PopupWindow 是阻塞式对话框。AlertDialog 弹出时,后台还可以做事情;PopupWindow 弹出时,程序会等待,在PopupWindow 退出前,程序一直等待,只有当我们调用了dismiss()方法的后,PopupWindow 退出,程序才会向下执行。我们在写程序的过程中可以根据自己的需要选择使用 Popupwindow 或者是 Dialog.两者最根本的区别在于有没有新建一个 window,PopupWindow 没有新建,而是通过 WMS 将 View 加到 DecorView;Dialog 是新建了一个 window (PhoneWindow),相当于走了一遍 Activity 中创建 window 的流程。
(详情自行阅读源码即可,两者的源码并不复杂)
本文探讨如何使用AlertDialog和PopupWindow实现对话框,并详细解析它们与Activity之间的区别。PopupWindow是一个悬浮窗口,能显示任意布局,而AlertDialog是Dialog的子类,常用于弹出对话。关键区别在于:AlertDialog弹出时后台仍可执行,PopupWindow则会阻塞程序,直至调用dismiss方法。此外,PopupWindow直接将View添加到DecorView,Dialog则新建一个window。
504





