美文网首页Android基础
2017-06-25-自定义ViewGroup

2017-06-25-自定义ViewGroup

作者: 王元 | 来源:发表于2019-07-29 23:16 被阅读0次

    自定义ViewGroup,一般分为四步走

    1,继承自ViewGroup

    public class CustomLayout extends ViewGroup {
        public CustomLayout(Context context, AttributeSet attr) {
        this(context, attr, 0);
    }
    
        public CustomLayout(Context context, AttributeSet attr, int defStyle) {
        super(context, attr, defStyle);
        }
    }
    

    2,自定义的ViewGroup的属性-在value文件下的attrs.xml声明如下代码

    <declare-styleable name="CustomLayout">
        <attr name="custom" format="integer" />
    </declare-styleable>
    

    然后在CustomLayout初始化的时候,获取自定义属性的值

    TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.CustomLayout);
    final int len = typedArray.getIndexCount();
    for (int i = 0; i < len; i++) {
    int styledAttr = typedArray.getIndex(i);
        switch (styledAttr) {
            case R.styleable.CustomLayout_custom:
                custom = typedArray.getInteger(i, 0);
                break;
            default:
                break;
        }
    }
    

    怎么使用这个自定义属性就不在此赘述了,相信大家都懂。。。

    3,覆盖onMeasure方法,测量值+测量模式来确定ViewGroup的大小

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        final int len = getChildCount();
        final int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = getPaddingTop();
        .....
        for (int i = 0; i < len; ++i) {
            View child = getChildAt(i);
            final ViewGroup.LayoutParams lp = child.getLayoutParams();
            int mode;
            if (lp.width > 0) {
                mode = MeasureSpec.EXACTLY;
            } else {
                if (lp.width == LayoutParams.MATCH_PARENT) {
                    mode = MeasureSpec.EXACTLY;
                } else {
                    mode = MeasureSpec.AT_MOST;
                }
            }
            final int childWidthSpec = MeasureSpec.makeMeasureSpec(numWidth, mode);
            final int childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
            
        }
        .....
        setMeasuredDimension(width, height + getPaddingBottom());
    }
    

    onMeasure的主要作用

    • 确定子view的宽和高,

    • 确定自己的宽和高。

    • 根据子View 的布局文件,为子view设置测量模式和测量值
      测量 = 测量模式+测量值
      测量模式由三种:

      EXCTLY:指定大小

      AT_MOST:指定最大的大小

      UNSPCIFIED:不指定大小,要多大就是多大。一般用于ScroolView中

    4,覆盖onLayout方法,指定每个子view的布局规则

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        final int len = getChildCount();
        final int width = r - l;
        .....
        int maxRowHeight = 0;
        for (int i = 0; i < len; ++i) {
            View child = getChildAt(i);
            final int childWidth = child.getMeasuredWidth();
            final int childHeight = child.getMeasuredHeight();
            .....
            child.layout(left, top, left + childWidth, top + childHeight);
            .....
        }
    }
    

    这样就是自定义viewGroup的流程,具体的逻辑需要根据自身的业务逻辑来确定,因此这里的代码作为参考

    相关文章

      网友评论

        本文标题:2017-06-25-自定义ViewGroup

        本文链接:https://www.haomeiwen.com/subject/pcjwrctx.html