\

\

\

What are LayoutParams?

LayoutParams is equivalent to a Layout information package, which encapsulates the Layout position, height, width and other information. If a View is added to a Layout that occupies an area of the screen, it is best to tell the Layout what the user expects it to be, by passing in an approved layoutParams. LayoutParams can be described in this way. On the chess board, each piece occupies a position, that is, each piece has a position information. For example, this piece is in 4 rows and 4 columns, where “4 rows and 4 columns” are the LayoutParams of the pieces.

But the LayoutParams class simply describes the width and height. Both can be set to three values: **** 1, a definite value; FILL_PARENT, that is, fill (the same size as the parent container); 3, WRAP_CONTENT, that is, wrap the component.

Decide that the LayoutParams of the ViewGroup, in this case, can support margins

Use the system’s MarginLayoutParams

<span style="font-size:18px;"> 	@Override
	public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs)
	{
		return new MarginLayoutParams(getContext(), attrs);
	}</span>
 
Copy the code

OnMeasure () measurements:

In ViewGroup, measure the height and width of childView, as well as the margin

ChildView is measured by measureChildren (width recommended by parent container, height recommended by parent container)

The high and wide

/** * Calculate the height and width of all chlseViews *, set the width and height of all chlseViews * by measureChildren method of ViewGroup. */ measureChildren(widthMeasureSpec, heightMeasureSpec);

Depending on the mode of the ViewGroup and the height and width of the childView,

And margin to set its own height and width

The mode is wrap_content (MeasureSpec.At_most)

Set your own height and width according to childView (width, height).

Otherwise, it is the recommended value of the parent container that you measure

	<span style="white-space:pre">	</span><span style="font-family:Times New Roman;">/** * Sets the width and height of the parent container * if it is wrap_content set to our value EXCATLY * otherwise: directly set to the value calculated by the parent container At_MOST */
			<span style="font-size:18px;"> setMeasuredDimension( (widthMode == MeasureSpec.EXACTLY) ? widthSpec: width, (heightMode == MeasureSpec.EXACTLY) ? heightSpec : height ); </span></span>Copy the code

OnLayout sets the position of the chidView, (sets the area to be drawn by childView) \

The position of childeView is determined by measuring the height and width, as well as the margin.

\

\

\

\

\

Custom ViewGroup:

package com.example.viewgroupdemo;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
import android.view.ViewGroup.MarginLayoutParams;
import android.widget.LinearLayout;

public class MyViewGroup extends ViewGroup {
	public MyViewGroup(Context context) {
		this(context, null);
	}
	public MyViewGroup(Context context, AttributeSet attrs) {
		this(context, attrs, 0);
	}

	public MyViewGroup(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
	}

	@Override
	protected void onLayout(boolean changed, int l, int t, int r, int b) {
		try {

			/ * * *TODO:Position all of its ChildViews (set the drawing area of the childView) * */
			int cCount = getChildCount();
			int cWidth = 0;
			int cHeight = 0;
			MarginLayoutParams marginLayoutParams = null;
			/*** * traverses all childViews according to their height, width, and margin ** /
			for (int i = 0; i < cCount; i++) {
				View  childView  = getChildAt(i);
				cWidth = childView.getMeasuredWidth();
				cHeight = childView.getMeasuredHeight();
				marginLayoutParams = (MarginLayoutParams) childView.getLayoutParams();
				// Four edges of childView
				int cl = 0, cr = 0, ct = 0, cb = 0;
				switch (i) {
				case 0:
					cl = marginLayoutParams.leftMargin;
					ct = marginLayoutParams.topMargin;
					break;
				case 1:
					cl = getWidth() - cWidth - marginLayoutParams.leftMargin - marginLayoutParams.rightMargin;
					ct = marginLayoutParams.topMargin;
					break;
				case 2:
					cl = marginLayoutParams.leftMargin;
					ct = getHeight() - marginLayoutParams.bottomMargin - cHeight;
					break;
				case 3:
					cl = getWidth() - cWidth - marginLayoutParams.rightMargin- marginLayoutParams.rightMargin;
					ct = getHeight() - cHeight - marginLayoutParams.bottomMargin;
					break;
				default:
					break; } cr = cl + cWidth; cb = ct + cHeight; childView.layout(cl, ct, cr, cb); }}catch(Exception e) { e.printStackTrace(); }}@Override
	public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs)
	{
		return new MarginLayoutParams(getContext(), attrs);
	}
 


	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		try {

			/ * * *TODO:Calculate all childView measurements, get the height and width, and set your own width and height */ based on childView calculations
			// Get the height and width recommended by the ViewGroup parent container, as well as the design mode
			int widthSpec = MeasureSpec.getSize(widthMeasureSpec);
			int widthMode = MeasureSpec.getMode(widthMeasureSpec);
			int heightSpec = MeasureSpec.getSize(heightMeasureSpec);
			int heightMode = MeasureSpec.getMode(heightMeasureSpec);

			/** * Calculate the height and width of all ChlseViews *, and set the width and height of all chlseViews * by measureChildren method of ViewGroup. When this line is completed, the width and height of childView have been calculated correctly */
			measureChildren(widthMeasureSpec, heightMeasureSpec);

			int width = 0;
			int height = 0;
			// The number of child Views,
			int mCount = getChildCount();

			int cWidth = 0;
			int cHeight = 0;
			MarginLayoutParams marginLayoutParams = null;

			// Calculate the height of the two left childViews
			int lHeight = 0;
			// Calculate the height of the two childViews. The final height is determined by lHeight and the maximum rHeight.
			int rHeight = 0;

			// Calculate the width of the two childViews above
			int tWidth = 0;
			// Calculate the width of the following two childViews. The final width is determined by the tWidth and bWidth maximums
			int bWidth = 0;

			/** * Calculates the width and height of the container based on the width and height calculated by childView and the set margin. * Is used for the container wrap_content */
			for (int i = 0; i < mCount; i++) {
				// Get the child view
				View childView = getChildAt(i);
				// Get the width and height measured by childView
				cWidth = childView.getMeasuredWidth();
				cHeight = childView.getMeasuredHeight();

				// Get MarginlayoutParams from the child view
				marginLayoutParams  =  (MarginLayoutParams) childView.getLayoutParams();
				// Iterate through four childViews

				// The top two widths
				if(i==0 || i==1){
					tWidth += cWidth +  
							marginLayoutParams.leftMargin + 
							marginLayoutParams.rightMargin; 
				}

				// Two widths below
				if(i==2 || i==3){
					bWidth += cWidth +  
							marginLayoutParams.leftMargin + 
							marginLayoutParams.rightMargin; 
				}

				// The height of the left two
				if(i == 0 || i == 2){
					lHeight += cHeight + 
							marginLayoutParams.topMargin
							+marginLayoutParams.bottomMargin;
				}

				// The height of the right two
				if(i == 1 || i == 3){
					rHeight += cHeight + 
							marginLayoutParams.topMargin
							+marginLayoutParams.bottomMargin;
				}

				// Calculate the height and width of the ViewGroup
				width = Math.max(tWidth, bWidth);
				height = Math.max(lHeight, rHeight);


				/** * Sets the width and height of the parent container * if it is wrap_content set to our value EXCATLY * otherwise: directly set to the value calculated by the parent container At_MOST */setMeasuredDimension( (widthMode == MeasureSpec.EXACTLY) ? widthSpec: width, (heightMode == MeasureSpec.EXACTLY) ? heightSpec : height ); }}catch(Exception e) { e.printStackTrace(); }}}Copy the code

Layout:

<com.example.viewgroupdemo.MyViewGroup
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:background="#AA333333" >

    <TextView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#FF4444"
        android:gravity="center"
        android:text="0"
        android:textColor="#FFFFFF"
        android:textSize="22sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#00ff00"
        android:gravity="center"
        android:text="1"
        android:textColor="#FFFFFF"
        android:textSize="22sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#ff0000"
        android:gravity="center"
        android:text="2"
        android:textColor="#FFFFFF"
        android:textSize="22sp"
        android:textStyle="bold" />

    <TextView
        android:layout_width="50dp"
        android:layout_height="50dp"
        android:background="#0000ff"
        android:gravity="center"
        android:text="3"
        android:textColor="#FFFFFF"
        android:textSize="22sp"
        android:textStyle="bold" />

</com.example.viewgroupdemo.MyViewGroup>
Copy the code

\

 

package com.example.viewgroupdemo; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; import android.view.ViewGroup.LayoutParams; import android.view.ViewGroup.MarginLayoutParams; import android.widget.LinearLayout; /** * Customise ViewGroup, add four TextViews (childView) * four corners ** onMeasure, * first get the height and width suggested by the parent of ViewGroup, and mode ** through this method, MeasureChildren (widthMeasureSpec, heightMeasureSpec); measureChildren(widthMeasureSpec, HeightMeasure); * Iterate through childView to calculate the height and width, MarginLayoutParams get margin * * // Get MarginLayoutParams by subview MarginLayoutParams = (MarginLayoutParams) childView.getLayoutParams(); SetMeasuredDemension (* (widthMode ==) setMeasuredDemension(* (widthMode ==) MeasureSpec.EXACTLY) ? widthSpec: width, (heightMode == MeasureSpec.EXACTLY) ? heightSpec : height * * ) * */ public class MyViewGroup extends ViewGroup { public MyViewGroup(Context context) { this(context, null); } public MyViewGroup(Context context, AttributeSet attrs) { this(context, attrs, 0); } public MyViewGroup(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { try { /** * TODO: * */ int cCount = getChildCount(); int cWidth = 0; int cHeight = 0; MarginLayoutParams marginLayoutParams = null; ** / for (int I = 0; i < cCount; i++) { View childView = getChildAt(i); cWidth = childView.getMeasuredWidth(); cHeight = childView.getMeasuredHeight(); marginLayoutParams = (MarginLayoutParams) childView.getLayoutParams(); Int cl = 0, cr = 0, ct = 0, cb = 0; switch (i) { case 0: cl = marginLayoutParams.leftMargin; ct = marginLayoutParams.topMargin; break; case 1: cl = getWidth() - cWidth - marginLayoutParams.leftMargin - marginLayoutParams.rightMargin; ct = marginLayoutParams.topMargin; break; case 2: cl = marginLayoutParams.leftMargin; ct = getHeight() - marginLayoutParams.bottomMargin - cHeight; break; case 3: cl = getWidth() - cWidth - marginLayoutParams.rightMargin- marginLayoutParams.rightMargin; ct = getHeight() - cHeight - marginLayoutParams.bottomMargin; break; default: break; } cr = cl + cWidth; cb = ct + cHeight; childView.layout(cl, ct, cr, cb); } } catch (Exception e) { e.printStackTrace(); } } @Override public ViewGroup.LayoutParams generateLayoutParams(AttributeSet attrs) { return new MarginLayoutParams(getContext(), attrs); } @override protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { */ / Get the height and width recommended by the parent of the ViewGroup. Int widthSpec = MeasureSpec. GetSize (widthMeasureSpec); int widthMode = MeasureSpec.getMode(widthMeasureSpec); int heightSpec = MeasureSpec.getSize(heightMeasureSpec); int heightMode = MeasureSpec.getMode(heightMeasureSpec); /** * Calculate the height and width of all chlseViews *, set the width and height of all chlseViews * by measureChildren method of ViewGroup. */ measureChildren(widthMeasureSpec, heightMeasureSpec); int width = 0; int height = 0; // The number of child views, int mCount = getChildCount(); int cWidth = 0; int cHeight = 0; MarginLayoutParams marginLayoutParams = null; Int lHeight = 0; // Calculate the height of the two childViews. The final height is determined by lHeight and the maximum rHeight. int rHeight = 0; Int tWidth = 0; // Calculate the width of two childViews. The final width is determined by tWidth and bWidth. Wrap_content (int I = 0; int I = 0; int I = 0; i < mCount; I ++) {// get the childView childView = getChildAt(I); / / get childView measure the width and height of cWidth = childView. GetMeasuredWidth (); cHeight = childView.getMeasuredHeight(); / / by child view for MarginlayoutParams MarginlayoutParams = (MarginlayoutParams) childView. GetLayoutParams (); Four childView / / / / traverse two width above the if (I = = 0 | | I = = 1) {tWidth + = cWidth + marginLayoutParams leftMargin + marginLayoutParams.rightMargin; } / / there are two below the width of the if (I = = 2 | | I = = 3) {bWidth + = cWidth + marginLayoutParams. LeftMargin + marginLayoutParams. RightMargin; } / / on the left side of the height of the two the if (I = = 0 | | I = = 2) {lHeight + = cHeight + marginLayoutParams. TopMargin + marginLayoutParams. BottomMargin; } / / on the right side of the height of the two the if (I = = 1 | | I = = 3) {rHeight + = cHeight + marginLayoutParams. TopMargin + marginLayoutParams. BottomMargin; } // Calculate the height and width of the ViewGroup width = math.max (tWidth, bWidth); height = Math.max(lHeight, rHeight); /** * Sets the width and height of the parent container * if it is wrap_content set to our value EXCATLY * otherwise: Directly set At_MOST */ setMeasuredDimension((widthMode == MeasureSpec.EXACTLY)? widthSpec: width, (heightMode == MeasureSpec.EXACTLY) ? heightSpec : height ); } } catch (Exception e) { e.printStackTrace(); }}}Copy the code

\

\

\

\

\


\