View 的布局和繪制

第二篇關于 View 的文章,主要說一下 View 的 layout 布局過程和 draw 繪制過程

根據第一篇 View 的測量 我們知道了 View 工作原理的具體流程,今天接著測量的過程往下進行。

View 的 layout 布局過程

目的:確定 View 的最終寬高,以及四個頂點的位置也就是在父 View 中的位置

  • ViewRootImpl 的 performMeasure 方法完成測量過程之后,就會接著調用 performLayout 方法,其中會調用 DecorView 的 layout 方法,并將右上角頂點位置,以及 DecorView 的寬高傳入,
  • layout 方法中會調用 setFrame方法并將位置參數傳入
  • setFrame 的過程是先確定在父容器的位置,為 mLeft,mTop,mRight,mBottom 以及 View 的最終寬高等參數賦值
  • layout() 方法中通過 setFrame() 方法來確定自己四個頂點的位置,四個頂點確定,View在父容器中的位置也就確定
  • 接著調用 onLayout() 方法,作用為父容器確定子元素的位置,得到子元素再父容器中的四個頂點的位置
  • 再在 onLayout() 方法中通過 setChildFrame() 方法調用子元素的 layout() 方法,將子元素四個頂點位置傳遞到子元素的layout()方法中,這樣子元素中再確定自己的位置
  • 一層一層傳遞下去就完成了 View 視圖樹的 layout 過程
  • 根據 layout 方法的參數,確定 View 寬高的最終大小

ViewGroup 的 layout

  1. layout 方法被調用,根據參數確定在父 View 中的位置
  2. onLayout 方法中,遍歷其子 View ,調用子 View 的 layout 并根據子 View 大小和父 View 對子 View 位置的限制傳入參數,完成布局過程向子 View 的傳遞

View 的 layout

  1. layout 方法被調用,確定在父 View 中的位置,完成布局

View 的 getMeasuredWidth() 和 getWidth() 的區別

  • 子元素的layout() 方法中會根據父容器中傳遞的頂點位置為 mLeft , mTop , mRight , mBottom 等屬性賦值,View 的 getWidth() 方法得到的值為 mRight - mLeft
  • View 的 getMeasuredWidth() 方法得到的值是 View 的 mMeasuredWidth 參數的值,該參數的賦值是在 onMeasure() 方法中
  • 所以這兩個方法得到的值不是同一個參數的值,兩個參數的賦值時間是不同的,如果View 重寫 layout 方法,修改四個頂點的位置,這樣兩個方法得到的值就是不同的
  • 所以不能說這兩值一定相等。getWidth() 方法得到的是 View 的最終寬高。
  • getHeight() 和 getMeasuredHeight() 方法同理。

View 的繪制

ViewRootImpl 的 performLayout 完成之后,performDraw 方法會被調用,開始繪制的過程。

View 繪制的過程

  1. 繪制背景 background.draw(canvas)
  2. 繪制自己 (onDraw)
  3. 繪制 children (dispatchDraw)
  4. 繪制裝飾 (onDrawScrollBars)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容