view测量的使用

实现一个自定义View我们需要继承View或viewgroup,并且实现三个方法。

onMeasure(int widthMeasureSpec, int heightMeasureSpec) 测量的方法有三种测量模式,这里的值是获取的父view给的测量值

  • MeasureSpec.UNSPECIFIED 父容器对子View没有任何约束,子 View 可以按自身需要,任意大小。

  • MeasureSpec.AT_MOST 大小由view自身确定,不能超过父容器大小。wrap_content对应的就是它

  • MeasureSpec.EXACTLY 固定宽高,宽高都已经可以确定了,不能超过指定的大小。 match_parent和写死的大小对应它

通过 getMode getSize 获得当前的模式和size

      int widthMode = MeasureSpec.getMode(widthMeasureSpec);
      int widthSize = MeasureSpec.getSize(widthMeasureSpec);
   注意在自定义view中获取子控件宽高都需要使用getMeasuredHeight|getMeasuredWidth

onLayout(int l, int t, int r, int b)
测量完后调用的方法,lt代表左上角的XY rb代表右下角的XY

**onDraw(Canvas canvas) **
知道了大小和怎么摆放现在就是画上去了


ViewGroup继承于View的子类 一个容器view继承它必须实现onLayout方法。调用顺序和View是一致的

下面是一段模仿LinearLayout的代码


public class TestGroup extends ViewGroup {

    public TestGroup(Context context) {
        super(context);
    }


    public TestGroup(Context context, AttributeSet attrs) {
        super(context, attrs);
    }


    public TestGroup(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        Log.i("jinwei", "onMeasure");
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        if (widthMode == MeasureSpec.AT_MOST &&
                heightMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(getWidthCount(), getHeightCount());
        } else if (widthMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(getMeasuredWidth(), heightSize);
        } else if (heightMode == MeasureSpec.AT_MOST) {
            setMeasuredDimension(widthSize, getHeightCount());
        } else {
            setMeasuredDimension(widthMeasureSpec, heightMeasureSpec);
        }
    }


    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        Log.i("jinwei", "onLayout");
        int count = getChildCount();
        //记录当前的高度位置
        int width = l;
        for (int i = 0; i < count; i++) {
            View childAt = getChildAt(i);
            int measuredHeight = childAt.getMeasuredHeight();
            int measuredWidth = childAt.getMeasuredWidth();
            childAt.layout(0, width, measuredWidth, measuredHeight + width);
            width += measuredHeight;
        }
    }


    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        Log.i("jinwei", "onDraw");
    }


    private int getHeightCount() {
        int count = getChildCount();
        int maxHeight = 0;
        for (int i = 0; i < count; i++) {
            int height = getChildAt(i).getMeasuredHeight();
            maxHeight += height;
        }
        return maxHeight;
    }


    private int getWidthCount() {
        int count = getChildCount();
        int maxWidth = 0;
        for (int i = 0; i < count; i++) {
            int width = getChildAt(i).getMeasuredWidth();
            maxWidth += width;
        }
        return maxWidth;
    }
}

你可能感兴趣的:(view测量的使用)