分析Android的View树

2018-03-16  本文已影响0人  言吾許

我们知道每一个Activity都包含一个Window窗口,在Android studio 中,通过双击Shift键,找到Window,然后单击它,我们去看一下Window的源码:


在AS中找源码

Window

/**
 * Abstract base class for a top-level window look and behavior policy.  An
 * instance of this class should be used as the top-level view added to the
 * window manager. It provides standard UI policies such as a background, title
 * area, default key processing, etc.
 *
 * <p>The only existing implementation of this abstract class is
 * android.view.PhoneWindow, which you should instantiate when needing a
 * Window.
 */
public abstract class Window {
...
  }

首先我们看到Window是一个抽象类,谷歌工程师在注释中解释的很清楚了:

An instance of this class should be used as the top-level view added to the window manager,It provides standard UI policies such as a background, title area, default key processing, etc:
一个此类的实例必须作为window manager的顶级view,它提供了比如:背景、标题等等。。
The only existing implementation of this abstract class is android.view.PhoneWindow, which you should instantiate when needing a Window:
此抽象类的唯一一个实现类是PhoneWindow,当你需要一个窗口时,应该实例化

PhoneWindow

public class PhoneWindow extends Window implements MenuBuilder.Callback {
   // This is the top-level view of the window, containing the window decor.
    private DecorView mDecor;
    // This is the view in which the window contents are placed. It is either
    // mDecor itself, or a child of mDecor where the contents go.
    ViewGroup mContentParent;
}

可以看到DecorView是作为window的顶级的view,而ViewGroup用来放置视图的内容,它有可能是DecorView本身也有可能是DecorView所包含的子内容(这里有点不太懂。。)

看看DecorView

public class DecorView extends FrameLayout implements RootViewSurfaceTaker, WindowCallbacks {
    ...
    private View mFloatingActionModeOriginatingView;
    // View added at runtime to draw under the status bar area
    private View mStatusGuard;
    // View added at runtime to draw under the navigation bar area
    private View mNavigationGuard;
    ...
}

DecorView继承自FrameLayout,我们那些ActionBar,ContentView都包含在这里面
mStatusGuard:在运行时候绘制在状态栏下
mNavigationGuard:在运行时候绘制在导航栏下
mFloatingActionModeOriginatingView:另外一个包含的view (?)

至此,我们可以得出外层的view嵌套关系如下:


窗口

DecorView中的view具体是怎么样的呢?我们可以先建一个HelloWorld工程,通过AS自带的Layout Inspector来分析层级,具体打开:Tools--->Android--->Layout Inspector


HelloWorld

我们可以看到DecorView下居然有三个子view,通过右边的尺寸可以得到
DecorView的height为:1920(说明实验机器为1920x1080的)
linearLayout的height为:1812
navigationBarBackground的height为:108
statusBarBackground的height为:72
通过小学数据可以得到:1920=1812+108,
再通过点击每个子view,可以发现,statusBarBackground应该包含在linearLayout中,所以结构图对应如下:


DecorView的子view

再接着看LinearLayout的子view:


image.png

为什么会有一个ViewStub 和一个LinearLayout呢?
通过查询PhoneWindow 中设置布局的代码

protected ViewGroup generateLayout(DecorView decor) {
    ...
     int features = getLocalFeatures();
     //一系列的if else,根据用户设置的主题去加载不同的布局
     if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
      ...
      }
    else if(..){
    ...  
    }else{
           // Embedded, so no decoration is needed.
            layoutResource = R.layout.screen_simple;
            // System.out.println("Simple!");
      }
  }

找到了关键的R.layout.screen_simple,也就是我们上面看到的那个布局,这就是为什么我们要在setContentView前面调用requesetFeature的原因。

FrameLayout只有一个子布局:ActionBarOverlayLayout,下面有一个content,里面包含的就是我们最熟悉的xml布局了,另一个子view是ActionBarContainer就是我们的ActionBar了

总结一下:

上一篇下一篇

猜你喜欢

热点阅读