The working principle of View (1): MeasureSpec

The basic process of measure

  1. The drawing process of View starts from ViewRootthe performTraversalsmethod of . It goes through three processes of measure, layout and draw to finally draw a View.
    • measure: measure the width and height of the View
    • layout: Determine the position of the View in the parent container
    • draw: Draw the View on the screen.
  2. performTraversalsWorkflow:
    image

    1. The parent container is onMeasurein, it will traverse the method of calling the child View measure.
    2. After all child Views are measurecompleted, the layout process will be entered, and the calling process is measuresimilar.
    3. layoutAfter the process is completed, the process is finally entered draw, and the process is measuresimilar, but performDrawthe transfer is realized by the method drawin the dispatchDrawmethod.
  3. Only after the Measure is completed, the measured width and height of the View can be passed getMeasureWidthand getMeasureHeightobtained. They are equivalent to the final width and height of the View in almost all cases, except in special cases.

    • Similarly, after the Layout is completed, the positions of the four vertices of the View can be obtained, and the final width and height of the View can be obtained through andgetWidth .getHeight
  4. DecorView is the top-level View.

    • Under normal circumstances, it will contain a vertical linear layout inside, with the title bar above and the content area below.
    • The layout file set in the Activity is setContentViewactually added to the content area.
    • The id of the content area can be obtained, and its ID is android.R.id.contentthe View we set for the first child View.
    • DecorView is one FramLayout, all events of the View layer go through first DecorView, and then are distributed level by level.

MeasureSpec

  1. Take a look at the source code roughly:

    public static class MeasureSpec {
        /** @hide */
        @IntDef({UNSPECIFIED, EXACTLY, AT_MOST})
        @Retention(RetentionPolicy.SOURCE)
        public @interface MeasureSpecMode {}
    
        private static final int MODE_SHIFT = 30;
        private static final int MODE_MASK  = 0x3 << MODE_SHIFT;
        public static final int UNSPECIFIED = 0 << MODE_SHIFT;
        public static final int EXACTLY     = 1 << MODE_SHIFT;
        public static final int AT_MOST     = 2 << MODE_SHIFT;
    
        public static int makeMeasureSpec(@IntRange(from = 0, to = (1 << View.MeasureSpec.MODE_SHIFT) - 1) int size, @MeasureSpecMode int mode) {
            if (sUseBrokenMakeMeasureSpec) {
                return size + mode;
            } else {
                return (size & ~MODE_MASK) | (mode & MODE_MASK);
            }
        }
    }
    @MeasureSpecMode
    public static int getMode(int measureSpec) {
        //noinspection ResourceType
        return (measureSpec & MODE_MASK);
    }
    
    public static int getSize(int measureSpec) {
        return (measureSpec & ~MODE_MASK);
    }

    Bit operations are widely used in Android source code, such as various FLAGs of Intent. They have higher efficiency and lower memory overhead.

    SpecMode has three categories:

    • EXACTLY: layout_width/ layout_heightSpecify as a specific value or match_parent, the parent container will specify an exact SpecSize.
    • AT_MOST: layout_width/ layout_heightSpecified as wrap_content, the parent container will specify a SpecSize of the available size, the size of the View cannot be larger than this value. The specific value depends on the specific implementation of different Views.
    • UNSPECIFIED: The parent container does not have any restrictions on the View. Developers will use it when drawing custom Views.
  2. MeasureSpecandLayoutParams

    • For DecorView, it MeasureSpecis determined by the size of the window and itself LayoutParams.

      • LayoutParams.MATCH_PARENT: Window can't resize. Froce root view to be windowSize. EXACTLY mode, the (forced) size is the size of the window.
      • LayoutParams.WRAP_CONTENT: Window can resize. Set max size for root view. AT_MOST mode, will set the maximum size for root view, but cannot exceed the window size.
      • Fixed size (such as specific dp value): Window wants to be an exact size. Force root view to be that size. EXACTLY mode, (force) root view size is the specified size.
    • The ordinary View is determined by the parent container MeasureSpecand itself LayoutParams, and is also related to the parent container padingand itself margin.

  3. MeasureSpecThe creation rules of ordinary View getChildMeasureSpeccan be understood by viewing the source code:

    Father Spec View size View的SpecSize View's SpecMode
    EXACTLY Fixed value>=0 Fixed value EXACTLY
    EXACTLY MATCH_PARENT 父SpecSize-padding EXACTLY
    EXACTLY WRAP_CONTENT 父SpecSize-padding AT_MOST
    AT_MOST Fixed value>=0 Fixed value EXACTLY
    AT_MOST MATCH_PARENT 父SpecSize-padding AT_MOST
    AT_MOST WRAP_CONTENT 父SpecSize-padding AT_MOST
    UNSPECIFIED Fixed value>=0 Fixed value EXACTLY
    UNSPECIFIED MATCH_PARENT 0 UNSPECIFIED
    UNSPECIFIED WRAP_CONTENT 0 UNSPECIFIED

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325611456&siteId=291194637