View 繪製流程知識小結

今天我們來複習下View的繪製流程。View是Android中所有控件的基類,是控件的一種抽象,代表了一個控件。

Android進階——Android視圖工作機制之measure、layout、draw

一、View樹的繪製流程

measure –> layout –> draw
測量 –> 佈局 –>繪製
measure :測量出View的寬/高;
layout:確定View最終寬/高四個頂點的位置;
draw:將View繪製在屏幕上;

二、measure

這裏寫圖片描述

1、ViewGroup.LayoutParams:

指定視圖寬度、高度的參數有 match_parent、wrap_content、固定值(100dp)三種。

2、MeasureSpec:

測量規則,代表一個32位的int值,將SpecMode、SpecSize包裝成一個int值來避免過多的對象內存分配;高2位代表SpecMode(測量模式), 低30位代表SpecSize(在某種測量模式下測量出的具體值)。

SpecMode 測量模式:
  • UNSPECIFIED:
    父容器不對View有任何限制,要多大給多大,一般用於系統內部,表示一種測量狀態。

  • EXACTLY:
    父容器檢測出View所需要的精確大小,這時候View的值就是SpecSize;它對應於LayoutParams中的 match_parent 和 具體的數值兩種模式。

  • AT_MOST:
    父容器指定了一個可用大小即SpecSize,View的大小不能大於這個值;它對應於LayoutParams中的 wrap_content 模式。

結論:

子View的MeasureSpec由父容器的MeasureSpec和自身的LayoutParams來共同決定的。
這裏寫圖片描述

3、measure的重要方法
  • measure(int widthMeasureSpec, int heightMeasureSpec)
    是一個final 方法子類無法重寫,會調用onMeasure方法,我們可以在onMeasure方法中處理測量的邏輯。
  • onMeasure(int widthMeasureSpec, int heightMeasureSpec)
    在onMeasure方法中處理測量的邏輯。
  • setMeasuredDimension(int measuredWidth, int measuredHeight)
    測量的終極方法,測量完成後進行調用,傳入測量出來的的寬、高值。

三、layout

這裏寫圖片描述

  • public void layout(int l, int t, int r, int b){}
    確定View本身的位置。

  • protected void onLayout(boolean changed, int left, int top, int right, int bottom) { }
    確定所有子元素的位置;
    父容器的位置確定後,它在onLayout中會遍歷所有的子元素並調用其layout方法,在layout方法中會調用onLayout方法。

四、draw

1、將View繪製在屏幕上,遵循如下幾步:

1、繪製背景:drawBackground(canvas);
2、繪製自己 : onDraw(canvas);
3、繪製childen :dispatchDraw(canvas);
4、繪製裝飾: onDrawForeground(canvas);

2、invalidate()、requestLayout()

invalidate()和requestLayout(),常用於View重繪和更新,其主要區別如下:

  • invalidate方法只會執行onDraw方法;

  • requestLayout方法只會執行onMeasure方法和onLayout方法,並不會執行onDraw方法;

所以當我們進行View更新時,若僅View的顯示內容發生改變且新顯示內容不影響View的大小、位置,則只需調用invalidate方法;若View寬高、位置發生改變且顯示內容不變,只需調用requestLayout方法;若兩者均發生改變,則需調用兩者,按照View的繪製流程,推薦先調用requestLayout方法再調用invalidate方法。

3、invalidate() 和 postInvalidate()

invalidate方法用於UI線程中重新繪製視圖
postInvalidate方法用於非UI線程中重新繪製視圖,省去使用handler

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章