美文网首页
Android 到底什么是Dialog?

Android 到底什么是Dialog?

作者: 赵勇Yaphet | 来源:发表于2017-10-17 22:26 被阅读392次
    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 窗口之后的内容变模糊
         */
    
    }
    
    

    相关文章

      网友评论

          本文标题:Android 到底什么是Dialog?

          本文链接:https://www.haomeiwen.com/subject/xfvjuxtx.html