android自定义ViewGroup--流式布局

android自定义ViewGroup--流式布局

 

个人觉得,自定义ViewGroup容器,核心是要确定里面每个子view的位置,ViewGroup的测量可以挪用源码中的是三种模式即可,个人开发去计算每个子view的大小显得相对复杂,系统自带的几种布局方式已足够使用,布局容器的核心还是在于子view的位置,测量和绘制使用默认的即可。


import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;

import java.util.List;


public class MyViewGroup extends ViewGroup {

    private Context mContext;
    private LayoutInflater layoutInflater;


    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);
        mContext = context;
        init();
    }

    private void init() {
        layoutInflater = LayoutInflater.from(mContext);

    }

    public void setTextViews(List<String> strings){
        List<String> content = strings;
        for (int i = 0; i < content.size(); i++) {
            TextView textView = (TextView) layoutInflater.inflate(R.layout.textview_child, this, false);
            textView.setText(content.get(i));
            this.addView(textView);
        }

    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        int childCount = getChildCount();

        int left = getLeft()+getPaddingLeft();
        int top = getTop()+getPaddingTop();
        int right = getRight()-getPaddingRight();
        int bottom = getBottom()-getPaddingBottom();

        int lines = 0;//布局到第几行
        for (int i = 0; i < childCount; i++) {
            View childAt = getChildAt(i);

            int childRight = left+ childAt.getMeasuredWidth();
            int childBottom = top+childAt.getMeasuredHeight();
            //换行
            if (childRight> right){
                lines++;

                left = getLeft()+getPaddingLeft();
                childRight = left+childAt.getMeasuredWidth();

                top = getTop()+getPaddingTop()+lines*childAt.getMeasuredHeight()+10*lines;
                childBottom = top+childAt.getMeasuredHeight();
            }
            if (childBottom <= bottom){
                //父容器的右上角作为layout的原点,所以需要减去父容器的起始值
                childAt.layout(left-l,top-t,childRight-l,childBottom-t);
                left += childAt.getMeasuredWidth()+10;
            }

        }

    }

    //ViewGroup没有实现onMeasure方法  而是在各个实现类layout下面去实现这个测量方法,因为不同的layout布局特性不同  无法做到统一的标准
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {



//        int measureWidth = 0;
//        int measureHeight = 0;
//
//        int childCount = getChildCount();//ViewGroup中view的数量
//
////        1.测量所有子view
//        measureChildren(widthMeasureSpec,heightMeasureSpec);//测量所有的子view  内部包含对子view的循环 调用了measureChild()

////        2.合并所有子View的尺寸大小,得到最终ViewGroup父layout的测量值
////            开发者需要根据自己定制的layout的特性来得到合并后的父layout的测量宽高
//
////        3.存储测量后view的大小值。
//        setMeasuredDimension(measureWidth,measureHeight);
//        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //触发所有子View的onMeasure函数去测量宽高
        measureChildren(widthMeasureSpec, heightMeasureSpec);
        //MeasureSpec封装了父View传递给子View的布局要求
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);



    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
    }
}