content: package yifeiyuan.practice.practicedemos.customview;
  
  import android.content.Context;
  import android.util.AttributeSet;
  import android.util.Log;
  import android.view.View;
  import android.view.ViewGroup;
  
  /**
   * Created by alanchen on 15/10/15.
   */
  public class MyViewGroup extends ViewGroup {
  
      public static final String TAG = MyViewGroup.class.getSimpleName();
  
      public MyViewGroup(Context context) {
          this(context, null);
      }
  
      public MyViewGroup(Context context, AttributeSet attrs) {
          this(context, attrs, 0);
      }
  
      public MyViewGroup(Context context, AttributeSet attrs, int defStyleAttr) {
          super(context, attrs, defStyleAttr);
          init();
      }
  
      //        int unspecified = MeasureSpec.UNSPECIFIED;//0
  //        int atMost = MeasureSpec.AT_MOST;//-2147483648
  //        int exactly = MeasureSpec.EXACTLY;//1073741824
      @Override
      protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
          // 0 0
  //        Log.d(TAG, "onMeasure: height" + getMeasuredHeight() + ";width:" + getMeasuredWidth());
  //        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
  //        Log.d(TAG, "onMeasure() called with: " + "widthMeasureSpec = [" + widthMeasureSpec + "], heightMeasureSpec = [" + heightMeasureSpec + "]");
  //        logModeAndSize(widthMeasureSpec);
  //        logModeAndSize(heightMeasureSpec);
  //        Log.d(TAG, "onMeasure: height" + getMeasuredHeight() + ";width:" + getMeasuredWidth());
  
          int height = 0;//group的计算高度
          int width = 0;//宽度
  
          int heightSize = MeasureSpec.getSize(heightMeasureSpec);
          int heightMode = MeasureSpec.getMode(heightMeasureSpec);
  
          int widthSize = MeasureSpec.getSize(widthMeasureSpec);
          int widthMode = MeasureSpec.getMode(widthMeasureSpec);
  
          int childcount = getChildCount();
          for (int i = 0; i < childcount; i++) {
              View child = getChildAt(i);
              //gone 的就无视掉
              if (child.getVisibility() == GONE) {
                  continue;
              }
              LayoutParams lp = child.getLayoutParams();
              int widthSpec = 0;
              int heightSpec = 0;
  
              //根据LayoutParams,给子View生成MeasureSpec规则
              if (lp.width == LayoutParams.WRAP_CONTENT) {
                  widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.AT_MOST);
              } else if (lp.width == LayoutParams.MATCH_PARENT) {
                  widthSpec = MeasureSpec.makeMeasureSpec(widthSize, MeasureSpec.EXACTLY);
              } else {
                  //其实xml里不会出现这样的情况
                  widthSpec = MeasureSpec.makeMeasureSpec(lp.width, MeasureSpec.EXACTLY);
              }
  
              if (lp.height == LayoutParams.WRAP_CONTENT) {
                  heightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.AT_MOST);
              } else if (lp.height == LayoutParams.MATCH_PARENT) {
                  heightSpec = MeasureSpec.makeMeasureSpec(heightSize, MeasureSpec.EXACTLY);
              } else {
                  heightSpec = MeasureSpec.makeMeasureSpec(lp.height, MeasureSpec.EXACTLY);
              }
  
              child.measure(widthSpec, heightSpec);
              //把所有的子View的高度加起来,就是高度
              height += child.getMeasuredHeight();
              // 拿子View中的最大宽度当自己的宽度,保证所有子View能够显示全
              width = Math.max(width, child.getMeasuredWidth());
              Log.d(TAG, "onMeasure: i:" + i + ",width:" + child.getMeasuredWidth() + ",height:" + child.getMeasuredHeight());
          }
  
          // 再根据父view给自己的spec,处理自己的宽高
          if (MeasureSpec.EXACTLY == widthMode) {
              width = widthSize;
          }else if (MeasureSpec.AT_MOST == widthMode) {
              width = Math.min(width, widthSize);
          }
  
          if (MeasureSpec.EXACTLY == heightMode) {
              height = heightSize;
          }else if (MeasureSpec.AT_MOST == heightMode) {
              height = Math.min(height, heightSize);
          }
  
          //一定要记得调用
          setMeasuredDimension(width, height);
  
          Log.d(TAG, "onMeasure: height" + getMeasuredHeight() + ";width:" + getMeasuredWidth());
  
      }
  
  
      private void logModeAndSize(int measureSpec) {
          switch (MeasureSpec.getMode(measureSpec)) {
              case MeasureSpec.UNSPECIFIED:
                  Log.d(TAG, "UNSPECIFIED: " + MeasureSpec.getSize(measureSpec));
                  break;
              case MeasureSpec.AT_MOST:
                  Log.d(TAG, "AT_MOST: " + MeasureSpec.getSize(measureSpec));
                  break;
              case MeasureSpec.EXACTLY:
                  Log.d(TAG, "EXACTLY: " + MeasureSpec.getSize(measureSpec));
                  break;
          }
      }
  
      private int measureHeight(int heightMeasureSpec) {
  
          int result = 100;
          int size = MeasureSpec.getSize(heightMeasureSpec);
          int mode = MeasureSpec.getMode(heightMeasureSpec);
          switch (mode) {
              case MeasureSpec.EXACTLY:
                  result = size;
                  break;
              case MeasureSpec.AT_MOST:
                  result = Math.min(result, size);
                  break;
              case MeasureSpec.UNSPECIFIED:
                  //看情况而定
                  // 这个是从RecyclerView的onMeasure里看来的.
                  //result = ViewCompat.getMinimumHeight(this);
                  break;
          }
          return result;
      }
  
      private int measureWidth(int widthMeasureSpec) {
          int result = 0;
          int size = MeasureSpec.getSize(widthMeasureSpec);
          int mode = MeasureSpec.getMode(widthMeasureSpec);
          if (mode == MeasureSpec.EXACTLY) {
              result = size;
          } else {
              result = 100;// 实际上需要自己计算
              if (mode == MeasureSpec.AT_MOST) {
                  //至多模式,别超过了
                  result = Math.min(result, size);
              }
          }
          return result;
      }
  
  
      @Override
      protected void onLayout(boolean changed, int l, int t, int r, int b) {
          int childcount = getChildCount();
          int height = 0;
          for (int i = 0; i < childcount; i++) {
              View child = getChildAt(i);
              if (child.getVisibility() == GONE) {
                  continue;
              }
              child.layout(l,t+height,l+child.getMeasuredWidth(),t+height+child.getMeasuredHeight());
              height += child.getMeasuredHeight();
              Log.d(TAG, "onLayout: i:" + i + ",width:" + child.getMeasuredWidth() + ",height:" + child.getMeasuredHeight());
          }
      }
  
      private void init() {
  
      }
  
      @Override
      protected void onFinishInflate() {
          super.onFinishInflate();
  //        Log.d(TAG, "onFinishInflate() called with: " + "");
      }
  
      @Override
      protected void onAttachedToWindow() {
          super.onAttachedToWindow();
  //        Log.d(TAG, "onAttachedToWindow() called with: " + "");
      }
  
      @Override
      protected void onDetachedFromWindow() {
          super.onDetachedFromWindow();
  //        Log.d(TAG, "onDetachedFromWindow() called with: " + "");
      }
  }