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

2020-07-10  本文已影响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的层级关系

想起之前的一个自定义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));
    }
...
上一篇下一篇

猜你喜欢

热点阅读