美文网首页
由一个小需求引来的对Window,DecorView总结

由一个小需求引来的对Window,DecorView总结

作者: 码农朱同学 | 来源:发表于2020-07-10 17:22 被阅读0次

    最近一个小伙伴离职,我接手那个他之前负责的App,这是一个很久很久之前的项目了,连那个小伙伴都是半途接手,可想而知代码是多么悠久醇香。最可怕的是产品也是新接手的,时常来问我一些页面上的问题。为了更快低了解整个代码结构以及解决产品的问题,就很有必要很快的定位到每个activity。所以就写了个简单的类:

    public class ShowActivityNameCallbacks implements Application.ActivityLifecycleCallbacks {
        @Override
        public void onActivityStarted(Activity activity) {
            if (activity == null) {
                return;
            }
            if (activity.getWindow() == null) {
                return;
            }
            if (activity.getWindow().getDecorView() == null) {
                return;
            }
            View decorView = activity.getWindow().getDecorView();
            FrameLayout fl = decorView.findViewById(android.R.id.content);
    
            String activityName = activity.getClass().getSimpleName();
    
            DragTextView textView = new DragTextView(activity, null);
            textView.setText(activityName);
            textView.setTextSize(13);
            textView.setTextColor(Color.parseColor("#00A443"));
            textView.setPadding(20, 20, 0, 0);
            textView.setLayoutParams(new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
    
            fl.addView(textView);
        }
        ...
    }
    
    

    效果如下:

    展示页面类名

    功能很简单,就是当每个类启动时,在左上角添加一个textview展示出类名。为了防止挡住UI细节,就让这个textview可以拖动。

            View decorView = activity.getWindow().getDecorView();
            FrameLayout fl = decorView.findViewById(android.R.id.content);
    

    从这里我们可以看到Activity中DecorView和PhoneWindow的层级关系

    • Window 类 位于 /frameworks/base/core/java/android/view/Window.java。该类是一个抽象类,提供了绘制窗口的一组通用API。可以将之理解为一个载体,各种View在这个载体上显示。
    • PhoneWindow类 位于/frameworks/policies/base/phone/com/android/internal/policy/impl/PhoneWindow.java。该类继承于Window类,是Window类的具体实现,即我们可以通过该类具体去绘制窗口。并且,该类内部包含了一个DecorView对象,该DectorView对象是所有应用窗口(Activity界面)的根View。 简而言之,PhoneWindow类是把一个FrameLayout类即DecorView对象进行一定的包装,将它作为应用窗口的根View,并提供一组通用的窗口操作接口。
    • DecorView类 该类是PhoneWindow类的内部类。该类是一个FrameLayout的子类,并且是PhoneWindow的子类,该类就是对普通的FrameLayout进行功能的扩展,更确切点可以说是修饰(Decor的英文全称是Decoration,即“修饰”的意思),比如说添加TitleBar(标题栏),以及TitleBar上的滚动条等 。最重要的一点是,它是所有应用窗口的根View 。

    想起之前的一个自定义view,在一个页面上加一个对话框蒙层。

      fun show(time: Long) {
            this.listener = listener
            // 解决崩溃问题
            if (this.parent != null) {
                (this.parent as ViewGroup).removeView(this)
            }
            // 在当前Activity加入本View
            val layoutParams = ViewGroup.LayoutParams(
                ViewGroup.LayoutParams.MATCH_PARENT,
                ViewGroup.LayoutParams.MATCH_PARENT
            )
            activity.addContentView(this, layoutParams)
            mAnimationView = this@H5LoadingDialog
            this.visibility = View.VISIBLE
            // 解决点击穿透的问题
            this.isClickable = true
    ...
    

    关键是这一句:

            activity.addContentView(this, layoutParams)
    

    其实与上面这两句一样的效果

            View decorView = activity.getWindow().getDecorView();
            FrameLayout fl = decorView.findViewById(android.R.id.content);
    

    所有上面的代码还可以这样写:

        @Override
        public void onActivityStarted(Activity activity) {
            if (activity == null) {
                return;
            }
            if (activity.getWindow() == null) {
                return;
            }
            if (activity.getWindow().getDecorView() == null) {
                return;
            }
            String activityName = activity.getClass().getSimpleName();
            DragTextView textView = new DragTextView(activity, null);
            textView.setText(activityName);
            textView.setTextSize(13);
            textView.setTextColor(Color.parseColor("#00A443"));
            textView.setPadding(20, 20, 0, 0);
    
            activity.addContentView(textView, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
        }
    

    所有他们的层级关系如下:


    层级关系

    比如这个:

    public abstract class BaseCardView extends FrameLayout {
    ...
        private void inflate() {
            rootV = LayoutInflater.from(ctx).inflate(initCardLayout(), this,false);
            this.removeAllViews();
            this.addView(new CardPlaceHolder(ctx, null));
        }
    ...
    

    相关文章

      网友评论

          本文标题:由一个小需求引来的对Window,DecorView总结

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