preface

Inherit the system viewGroup to achieve the desired effect. DecorView & Window: A custom View is a custom View, and a custom View is a custom View. MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec = MeasureSpec GetWidth () and getMeasuredWidth() get the width and height of a View. Android: Why does view.post() guarantee the width and height of the view? Android: hand-by-hand take you clear comb custom View work process Android custom View actual situation series: timeline use high-grade knowledge of RecycleView Android custom View: do you need a simple and easy to use, with historical search records of the search box? Android: Hand teach you to write a complete custom View Path class most comprehensive explanation – custom View application series Canvas class most comprehensive explanation – custom View application series

The effect

Implementation approach

Customize the viewGroup control core implementation methods :onMeasure() and onLayout().

Measurement process onMeasure

    1. Super. onMeasure(widthMeasureSpec, heightMeasureSpec);
    1. Mode/Size MeasureSpec. GetMode (widthMeasureSpec);
    1. Measure int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width); int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height); child.measure(childWidthSpec, childHeightSpec);
    1. Get the size of the child View after measurement
    1. The ViewGroup calculates its own size according to its own situation, which involves specific logic processing in specific scenarios
    1. Save its own size setMeasuredDimension(Width,height);

Layout process onLayout

    1. Iterate over the child View for
    1. Define your own rules
    1. The measurement of the child View
    1. left,top,right,bottom
    1. child.layout

Demo1

package com.essence.wanapp; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; Public class MyViewGroup extends viewGroup {private int OFFSET = 100; public class MyViewGroup extends viewGroup {private int OFFSET = 100; public MyViewGroup(Context context) { super(context); } public MyViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } public MyViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { super.onMeasure(widthMeasureSpec, heightMeasureSpec); MeasureChildren (widthMeasureSpec, heightMeasureSpec); int width = 0; int height = 0; for (int i = 0; i < getChildCount(); I ++) {// Max width = math.max (width, I * OFFSET + getChildAt(I).getMeasuredWidth()); // Height = height + measureDHeight (I).measuredHeight (); } // Set the current viewGroup width and height setMeasuredDimension(width, height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { int childCount = getChildCount(); int top = 0; int left = 0; int bottom = 0; int right = 0; for (int i = 0; i < childCount; i++) { View childAt = getChildAt(i); left = OFFSET * i; right = left + childAt.getMeasuredWidth(); bottom = top + childAt.getMeasuredHeight(); ChildAt. Layout (left, top, right, bottom); top = top + childAt.getMeasuredHeight(); }}}Copy the code

Demo2 is written in the same way, mainly considering the width, height and height measurement mode provided by the current viewGroup system

package com.zero.myviewgroupdemo01; import android.content.Context; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; public class MyViewGroup extends ViewGroup { private static final int OFFSET = 100; Public MyViewGroup(Context Context) {super(Context); } public MyViewGroup(Context context, AttributeSet attrs) { super(context, attrs); } public MyViewGroup(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { //1. Super. onMeasure(widthMeasureSpec, heightMeasureSpec); Mode/Size int widthMode = MeasureSpec. GetMode (widthMeasureSpec); int widthSize = MeasureSpec.getSize(widthMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); int heightSize = MeasureSpec.getSize(heightMeasureSpec); Int childCount = getChildCount(); childCount = childCount (); For (int I = 0; i < childCount; i++) { View child = getChildAt(i); ViewGroup.LayoutParams lp = child.getLayoutParams(); int childWidthSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width); int childHeightSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height); child.measure(childWidthSpec, childHeightSpec); } int width = 0; int height = 0; Switch (widthMode) {case MeasureSpec.EXACTLY: width = widthSize; break; case MeasureSpec.AT_MOST: case MeasureSpec.UNSPECIFIED: for (int i = 0; i < childCount; i++) { View child = getChildAt(i); int widthAddOffset = i * OFFSET + child.getMeasuredWidth(); width = Math.max(width, widthAddOffset); } break; default: break; } switch (heightMode){ case MeasureSpec.EXACTLY: height =heightSize; break; case MeasureSpec.AT_MOST: case MeasureSpec.UNSPECIFIED: for (int i = 0; i < childCount; i++) { View child = getChildAt(i); height += child.getMeasuredHeight(); } break; default: break; } //6. Save the measuredDimension (width,height); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { // 1. // 2. Define your rules // 3. // 4. Left,top,right,bottom // 6. Child. Layout int left = 0; int top = 0; int right = 0; int bottom = 0; int childCount = getChildCount(); for(int i = 0; i < childCount; i++){ View child = getChildAt(i); left = i * OFFSET; right = left + child.getMeasuredWidth(); bottom = top + child.getMeasuredHeight(); child.layout(left,top,right,bottom); top += child.getMeasuredHeight(); }}}Copy the code