美文网首页
分析Android的View树

分析Android的View树

作者: 言吾許 | 来源:发表于2018-03-16 16:23 被阅读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了

    总结一下:

    • Window是一个抽象类,里面含有背景,标题等的一些方法,而PhoneWindow是Window的唯一的实现类,通过DecorView来添加顶级视图
    • Activity中的Window通过getWindow获取
    • 我们在setContentView的xml布局体现在@id/content里

    相关文章

      网友评论

          本文标题:分析Android的View树

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