Giter Site home page Giter Site logo

customview5's Introduction

CustomView5

自定义ViewGroup学习
按着hongyang的博客写了这个自定义ViewGroup的案例,实现效果:自定义的ViewGroup可以作为根布局使用,内部可以有四个以内的子控件,子控件会分别位于自定义 ViewGroup的左上,右上,左下,右下位置.
思路:一,重写ViewGroup的onMeasure(...),在onMeasure中对子控件进行宽高测量,然后根据MeasureSpec的SpecMode得出自定义ViewGroup的最终宽高.
代码:使用measureChildren(...)对子控件进行遍历测量,但是使用这种方式好像子控件设置margin会没有作用,网上说要用measureChildWithMargins(...),但是我不会用 ,见相关文章http://www.jianshu.com/p/5fbb1ce3c7f0.
这里有一个概念SpecMode,它有三种数值
MeasureSpec.EXACTLY:精确模式,此时控件的尺寸是固定的,一般是在布局文件中已经写死的.
MeasureSpec.AT_MOST:最大模式,此时控件的尺寸是可变化的,但是它不会超出父控件给定的范围,对应布局文件中的wrap_content和match_parent.
MeasureSpec.UNSPECIFIED:未指定模式,当前控件大小不受限定,出现的情况比较少,一般是用不到的.

    @Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    /**
     * 获得此ViewGroup的上级容器为其推荐的宽和高,以及计算模式
     */
    int widthMode = MeasureSpec.getMode(widthMeasureSpec);
    int widthSize = MeasureSpec.getSize(widthMeasureSpec);
    int heightMode = MeasureSpec.getMode(heightMeasureSpec);
    int heightSize = MeasureSpec.getSize(heightMeasureSpec);

    int cCount = getChildCount();

//        for (int i = 0; i < cCount; i++) {
//            View childView = getChildAt(i);
//            //childView.measure(widthMeasureSpec,heightMeasureSpec);
//            measureChildWithMargins(childView, widthMeasureSpec, 0, heightMeasureSpec, 0);
//        }

    /**测量一次所有的childView的宽和高***/
    measureChildren(widthMeasureSpec, heightMeasureSpec);


    int width = 0;
    int height = 0;


    int cWidth = 0;
    int cHeight = 0;

    MarginLayoutParams cParams = null;
    //用于计算左边两个childView的高度
    int lHeight = 0;
    //用于计算右边两个childView的高度,最终高度取两者之间大值
    int rHeight = 0;

    //用于计算上边两个childView的宽度
    int tWidth = 0;
    //用于计算下面两个childView的宽度,最终宽度取两者之间大值
    int bWidth = 0;

    //遍历ChildView,计算出容器是wrap_content时的宽和高
    for (int i = 0; i < cCount; i++) {
        View childView = getChildAt(i);
        cWidth = childView.getMeasuredWidth();
        cHeight = childView.getMeasuredHeight();
        cParams = (MarginLayoutParams) childView.getLayoutParams();

        if (i == 0 || i == 1) {
            tWidth += cWidth + cParams.leftMargin + cParams.rightMargin;
        }

        if (i == 2 || i == 3) {
            bWidth += cWidth + cParams.leftMargin + cParams.rightMargin;
        }

        if (i == 0 || i == 2) {
            lHeight += cHeight + cParams.topMargin + cParams.bottomMargin;
        }

        if (i == 1 || i == 3) {
            rHeight += cHeight + cParams.topMargin + cParams.bottomMargin;
        }
    }

    width = Math.max(tWidth, bWidth);
    height = Math.max(lHeight, rHeight);

    /**
     * 如果是wrap_content设置为我们计算的值
     * 否则:直接设置为父容器计算的值
     */
    setMeasuredDimension(widthMode == MeasureSpec.EXACTLY ? widthSize : width,
            heightMode == MeasureSpec.EXACTLY ? heightSize : height);

}

二,重写onLayout(...),对子控件的位置进行限定.

    @Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
    int cCount = getChildCount();
    int cWidth = 0;
    int cHeight = 0;
    MarginLayoutParams cParams = null;

    /**
     * 遍历所有childView,根据其宽和高,以及margin进行布局
     */
    for (int i = 0; i < cCount; i++) {
        View childView = getChildAt(i);
        cWidth = childView.getMeasuredWidth();
        cHeight = childView.getMeasuredHeight();
        cParams = (MarginLayoutParams) childView.getLayoutParams();

        int cl = 0, ct = 0, cr = 0, cb = 0;
        switch (i) {
            case 0:
                cl = cParams.leftMargin;
                ct = cParams.topMargin;
                break;
            case 1:
                cl = getWidth() - cWidth - cParams.rightMargin;
                ct = cParams.topMargin;
                break;
            case 2:
                cl = cParams.leftMargin;
                ct = getHeight() - cHeight - cParams.bottomMargin;
                break;
            case 3:
                cl = getWidth() - cWidth - cParams.rightMargin;
                ct = getHeight() - cHeight - cParams.bottomMargin;
                break;
        }
        cr = cl + cWidth;
        cb = ct + cHeight;
        childView.layout(cl, ct, cr, cb);
    }

}

customview5's People

Contributors

liuhuan2015 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.