This is the 19th day of my participation in the Gwen Challenge in November. Check out the details: The last Gwen Challenge in 2021
The layout process
The View’s measure process is followed by the View’s layout process. The Layout procedure is relatively simple compared to the measure procedure. The Layout procedure starts with the ViewRootImpl’s pergormLayout() method, and performLayout() calls Layout().
public void layout(int l, int t, int r, int b) {
if((mPrivateFlags3 & PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT) ! =0) {
onMeasure(mOldWidthMeasureSpec, mOldHeightMeasureSpec);
mPrivateFlags3 &= ~PFLAG3_MEASURE_NEEDED_BEFORE_LAYOUT;
}
int oldL = mLeft;
int oldT = mTop;
int oldB = mBottom;
int oldR = mRight;
boolean changed = isLayoutModeOptical(mParent) ?
setOpticalFrame(l, t, r, b) : setFrame(l, t, r, b);
if (changed || (mPrivateFlags & PFLAG_LAYOUT_REQUIRED) == PFLAG_LAYOUT_REQUIRED) {
onLayout(changed, l, t, r, b);
if (shouldDrawRoundScrollbar()) {
if(mRoundScrollbarRenderer == null) {
mRoundScrollbarRenderer = new RoundScrollbarRenderer(this); }}else {
mRoundScrollbarRenderer = null;
}
mPrivateFlags &= ~PFLAG_LAYOUT_REQUIRED;
ListenerInfo li = mListenerInfo;
if(li ! =null&& li.mOnLayoutChangeListeners ! =null) {
ArrayList<OnLayoutChangeListener> listenersCopy =
(ArrayList<OnLayoutChangeListener>)li.mOnLayoutChangeListeners.clone();
int numListeners = listenersCopy.size();
for (int i = 0; i < numListeners; ++i) {
listenersCopy.get(i).onLayoutChange(this, l, t, r, b, oldL, oldT, oldR, oldB);
}
}
}
mPrivateFlags &= ~PFLAG_FORCE_LAYOUT;
mPrivateFlags3 |= PFLAG3_IS_LAID_OUT;
}
Copy the code
Layout method to implement the process, first through the setFrame method to set the View of the four vertex position: mLeft, mRight, mTop, mBottom. Once you’ve determined the coordinates, you can get the View’s position in the parent container. The onLayout method is then called, but onLayout is not implemented in the View, nor in the ViewGroup, so the onLayout method is implemented in the concrete implementation class. You can use the class LinearLayout method to learn how to implement it.
protected void onLayout(boolean changed, int l, int t, int r, int b) {
if (mOrientation == VERTICAL) {
layoutVertical(l, t, r, b);
} else{ layoutHorizontal(l, t, r, b); }}Copy the code
The layoutVertical method iterates through all the child views and calls their setChildFrame method to determine the position of the child view. During this process, childTop will grow gradually, and subsequent child views will be placed lower, in line with the vertical layout properties. The parent container also calls the child view’s Layout method after the layout method completes its position, and then the child view determines its position. View tree through a layer of layout method transfer call to complete the whole tree location information positioning.
The draw process
View draw step process is mainly divided into the following points:
- Draw the background (save the canvas layer if necessary)
- draw
View
The content of the - Draw child View (save canvas layer if necessary)
- Decorator class additional properties such as draw borders
public void draw(Canvas canvas) {
final int privateFlags = mPrivateFlags;
mPrivateFlags = (privateFlags & ~PFLAG_DIRTY_MASK) | PFLAG_DRAWN;
// Step 1, draw the background, if needed
intsaveCount; drawBackground(canvas); .// Step 2, save the canvas' layers
// Step 3, draw the content
onDraw(canvas);
// Step 4, draw the children
dispatchDraw(canvas);
// Step 5, draw the fade effect and restore layers
// Step 6, draw decorations (foreground, scrollbars)
onDrawForeground(canvas);
// Step 7, draw the default focus highlightdrawDefaultFocusHighlight(canvas); }}Copy the code
Skip drawBackground(canvas) to focus on the implementation of onDraw(canvas) and dispatchDraw(canvas). There is no empty implementation of the onDraw(Canvas) method in View and ViewGroup. DispatchDraw (Canvas) is implemented in the ViewGroup in the implementation class. But you can also, in general, see that drawing draws itself first and then distributing the drawing to draw its subviews. So drawing is done through the dispatchDraw(canvas) method one layer at a time to the subview.
In addition, the View has a method called setWillNotDraw, which can be marked as true when the View doesn’t need to draw anything and is optimized internally. View does not enable optimization by default, but ViewGroup does. This is important when developing custom views that inherit from viewGroups. You need to turn off the WILL_not_DRAW flag when using the onDraw method.