Android 到底什么是Dialog?
程序员文章站
2022-05-19 13:16:37
...
package zhaoyong.mylibrary;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.TextView;
/**
* Created by ZhaoYong on 2017/10/17.
* 什么是Dialog
*/
public class 什么是Dialog extends Activity {
void MyDialog() {
//test code
Dialog dialog = new Dialog(this);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Title")
.setMessage("Dialog content.")
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
})
.show();
/*
* Dialog:
* implements DialogInterface, Callback, android.view.KeyEvent.Callback, OnCreateContextMenuListener
*
* Activity Dialog Popupwindow Toast Snackbar 都属于显示控件
* Fragment 不属于显示控件,而是显示组件
*
* Activity Dialog PopupWindow Toast Snackbar 类的内部都管理维护着一个Window对象
* 这个Window对象不但是一个View组件的集合管理对象,它也实现了组件的加载与绘制流程
*
* Dialog源码中实现了getWindow()方法获取其中的Window对象
* Fragment中没有Window对象
*
* 设计模式:Dialog是建造者模式,可看AlertDialog.Builder
*/
// Dialog构造方法
/*
Dialog(@NonNull Context context, @StyleRes int themeResId, boolean createContextThemeWrapper) {
if (createContextThemeWrapper) {
if (themeResId == 0) {
final TypedValue outValue = new TypedValue();
context.getTheme().resolveAttribute(R.attr.dialogTheme, outValue, true);
themeResId = outValue.resourceId;
}
mContext = new ContextThemeWrapper(context, themeResId);
} else {
mContext = context;
}
mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
final Window w = new PhoneWindow(mContext);
mWindow = w;
w.setCallback(this);
w.setOnWindowDismissedCallback(this);
w.setWindowManager(mWindowManager, null, null);
w.setGravity(Gravity.CENTER);
mListenersHandler = new ListenersHandler(this);
}
*/
/*
* 直接构造了一个PhoneWindow,并赋值给Dialog的成员变量mWindow
* Dialog和Activity的显示逻辑都是类似的,都是通过对应的Window变量来实现窗口的加载与显示的
* mWindowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
*/
// window类的setWindowManager方法:
/*
public void setWindowManager(WindowManager wm, IBinder appToken, String appName,
boolean hardwareAccelerated) {
mAppToken = appToken;
mAppName = appName;
mHardwareAccelerated = hardwareAccelerated
|| SystemProperties.getBoolean(PROPERTY_HARDWARE_UI, false);
if (wm == null) {
wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
}
mWindowManager = ((WindowManagerImpl)wm).createLocalWindowManager(this);
}
*/
/*
总结:
Dialog和Activity的显示逻辑是相似的都是内部管理这一个Window对象
用WIndow对象实现界面的加载与显示逻辑
Dialog中的Window对象与Activity中的Window对象是相似的,都对应着一个WindowManager对象
Dialog相关的几个类:Dialog,AlertDialog,AlertDialog.Builder,AlertController,AlertController.AlertParams
其中Dialog是窗口的父类,主要实现Window对象的初始化和一些共有逻辑
而AlertDialog是具体的Dialog的操作实现类,AlertDialog.Builder类是AlertDialog的内部类
主要用于构造AlertDialog,AlertController是AlertDialog的控制类
AlertController.AlertParams类是控制参数类
构造显示Dialog的一般流程:
构造AlertDialog.Builder,然后设置各种属性,最后调用AlertDialog.Builder.create方法获取AlertDialog对象
并且create方法中会执行,构造AlertDialog,设置dialog各种属性的操作
最后我们调用Dialog.show方法展示窗口,初始化Dialog的布局文件,Window对象等
然后执行mWindowManager.addView方法,开始执行绘制View的操作,并最终将Dialog显示出来
*/
}
/**
* 要理解什么是dialog就要理解什么是window
*/
Window window;
// Window表示的是一个窗口的概念,它是一个抽象类,它的具体实现是PhoneWindow
// 权限:android.permission.SYSTEM_ALERT_WINDOW
@SuppressLint("RtlHardcoded")
public void show(String content, int layoutId) {
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
WindowManager.LayoutParams params = new WindowManager.LayoutParams();
// 加载布局
View view = View.inflate(this, layoutId, null);
// 设置浮窗params属性
params.width = WindowManager.LayoutParams.WRAP_CONTENT;
params.height = WindowManager.LayoutParams.WRAP_CONTENT;
params.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
params.type = WindowManager.LayoutParams.TYPE_PHONE;
params.gravity = Gravity.TOP + Gravity.LEFT;// 将重心设置为左上方
params.format = PixelFormat.TRANSLUCENT;// 半透明
params.x = 100;// 设置显示位置
params.y = 100;
TextView tvLocation = new TextView(this);
tvLocation.setText("");
tvLocation.setText(content);
// 将View添加到窗体管理器
wm.addView(view, params);
}
/*
* 所以,什么是Dialog?
* Dialog Popupwindow Toast Snackbar
* 这些都是内置Window对象,通过Window显示封装好的显示控件
* 以上都是个人理解
* 这些显示控件都是基于window的各个属性创建出来用于在界面上显示的
*/
/*
* Window属性:
* LayoutParams.Flags参数表示Window的属性,通过设置它的选项可以控制Window的显示特性。如下几种常见选项:
* FLAG_NOT_FOCUSABLE 不许获得焦点
* FLAG_NOT_TOUCHABLE 不接受触摸屏事件
* FLAG_NOT_TOUCH_MODAL 当窗口可以获得焦点(没有设置 FLAG_NOT_FOCUSALBE 选项)时,仍然将窗口范围之外的点设备事件(鼠标、触摸屏)发送给后面的窗口处理。否则它将独占所有的点设备事件,而不管它们是不是发生在窗口范围内。
* FLAG_SHOW_WHEN_LOCKED 当屏幕锁定时,窗口可以被看到。这使得应用程序窗口优先于锁屏界面。可配合FLAG_KEEP_SCREEN_ON选项点亮屏幕并直接显示在锁屏界面之前。可使用FLAG_DISMISS_KEYGUARD选项直接解除非加锁的锁屏状态。此选项只用于最顶层的全屏幕窗口。
* FLAG_DIM_BEHIND 窗口之后的内容变暗
* FLAG_BLUR_BEHIND 窗口之后的内容变模糊
*/
}
上一篇: 简单计算空气质量指数
下一篇: 使用LDA(潜在迪利克雷)进行文本聚类