后附源码地址

思路:
1、自定义View;
2、由于这个View是要包含其他控件,所以继承ViewGroup;
3、设置这个自定义View的LayoutParams,重写generateLayoutParams,这里设置的是MarginLayoutParams;
4、重写OnMeasure,计算该容器的大小和子元素的大小
5、重写OnLayout,设置子控件的位置

这里需要注意:该空间的模式
**warp_content: MeasureSpec.AT_MOST 需要根据子布局的大小设置该控件的大小。
fill_parent和mach_parent:MeasureSpec.EXACTLY 直接使用获取大小即可**

int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);

FlowView.java

package com.ucloud.oxpecker.views;import java.util.ArrayList;import java.util.List;import android.content.Context;import android.util.AttributeSet;import android.view.View;import android.view.ViewGroup;public class FlowView extends ViewGroup {    public FlowView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);    }    public FlowView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public FlowView(Context context) {        super(context);    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);        int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);        int modeWidth = MeasureSpec.getMode(widthMeasureSpec);        int modeHeight = MeasureSpec.getMode(heightMeasureSpec);        // warp_content        int width = 0, height = 0, lineWidth = 0, lineHeight = 0;        for (int i = 0; i < getChildCount(); i++) {            View child = getChildAt(i);            measureChild(child, widthMeasureSpec, heightMeasureSpec);            MarginLayoutParams params = (MarginLayoutParams) child                    .getLayoutParams();            int childWidth = child.getMeasuredWidth() + params.leftMargin                    + params.rightMargin;            int childHeight = child.getMeasuredHeight() + params.topMargin                    + params.bottomMargin;            if (childWidth + lineWidth > sizeWidth - getPaddingLeft()                    - getPaddingRight()) {                // 对比得到最大宽度                width = Math.max(lineWidth, width);                // 重置lineWidth                lineWidth = childWidth;                // 记录行高                height += lineHeight;                lineHeight = childHeight;            } else {                lineWidth += childWidth;                lineHeight = Math.max(lineHeight, childHeight);            }            if (i == getChildCount() - 1) {                width = Math.max(lineWidth, width);                height += lineHeight;            }        }        setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth                : width + getPaddingLeft() + getPaddingRight(),                modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height                        + getPaddingTop() + getPaddingBottom());    }    private List> mAllViews = new ArrayList>();    // 每一行的高度    private List mLineHeight = new ArrayList();    // 每一行距离左边的距离    private List mLineMarginLeft = new ArrayList();    @Override    protected void onLayout(boolean changed, int l, int t, int r, int b) {        mAllViews.clear();        mLineHeight.clear();        int width = getMeasuredWidth();        int lineWidth = 0, lineHeight = 0;        List lineViews = new ArrayList();        for (int i = 0; i < getChildCount(); i++) {            View child = getChildAt(i);            MarginLayoutParams params = (MarginLayoutParams) child                    .getLayoutParams();            int childWidth = child.getMeasuredWidth() + params.leftMargin                    + params.rightMargin;            int childHeight = child.getMeasuredHeight() + params.topMargin                    + params.bottomMargin;            if (childWidth + lineWidth > width - getPaddingLeft()                    - getPaddingRight()) {                // 计算每行距离左边距离                int lineLeftMargin = (width - lineWidth) / 2;                mLineMarginLeft.add(lineLeftMargin);                // 行高                mLineHeight.add(lineHeight);                mAllViews.add(lineViews);                lineWidth = 0;                lineHeight = childHeight;                lineViews = new ArrayList();            }            lineWidth += childWidth;            lineHeight = Math.max(lineHeight, childHeight);            lineViews.add(child);        }        /** 处理最后一行 **/        // 计算每行距离左边距离        int lineLeftMargin = (width - lineWidth) / 2;        mLineMarginLeft.add(lineLeftMargin);        // 行高        mLineHeight.add(lineHeight);        mAllViews.add(lineViews);        /** 设置子View的位置 **/        int left = getPaddingLeft(), top = getPaddingTop();        for (int i = 0; i < mAllViews.size(); i++) {            lineViews = mAllViews.get(i);            lineHeight = mLineHeight.get(i);            // 居中显示的左边距            left += mLineMarginLeft.get(i);            for (int j = 0; j < lineViews.size(); j++) {                View child = lineViews.get(j);                if (child.getVisibility() == View.GONE)                    continue;                MarginLayoutParams params = (MarginLayoutParams) child                        .getLayoutParams();                int lc = left + params.leftMargin;                int tc = top + params.topMargin;                int rc = lc + child.getMeasuredWidth();                int bc = tc + child.getMeasuredHeight();                child.layout(lc, tc, rc, bc);                left += child.getMeasuredWidth() + params.leftMargin                        + params.rightMargin;            }            left = getPaddingLeft();            top += lineHeight;        }    }    @Override    public LayoutParams generateLayoutParams(AttributeSet attrs) {        return new MarginLayoutParams(getContext(), attrs);    }}

调用方式

FlowView flowViewRecive = (FlowView) findViewById(R.id.flowView_recive);flowView.removeAllViews();AttrTextView tv = new AttrTextView(this);MarginLayoutParams lp = new MarginLayoutParams(LayoutParams.WRAP_CONTENT,LayoutParams.WRAP_CONTENT);tv.setText("测试");lp.leftMargin = 10;lp.rightMargin = 10;lp.topMargin = 5;lp.bottomMargin = 5;tv.setBackgroundResource(R.drawable.shape_tv_email);tv.setTextColor(getResources().getColor(R.color.black));flowView.addView(tv, lp);

源码下载

更多相关文章

  1. Android(安卓)Studio无法运行模拟器或者真机的问题
  2. Android——SlidingMenu学习总结
  3. Android(安卓)View初始化基本流程
  4. Android仿微信底部菜单
  5. Android中DialogFragment的简单使用及常见问题
  6. android TextView空间的setTextSize()方法在真机上运行大小问题
  7. Android(安卓)界面适配笔记
  8. Android(安卓)开发学习进程0.15 adb cardview framelayout 控件
  9. android notification的用法

随机推荐

  1. ubuntu10.10下的android源码下载及编译
  2. Android与php服务器交互实例
  3. Android Activity实现切换动画的两种方法
  4. 在Android 的Camera 预览上执行 Drawing
  5. android发送json并解析返回json
  6. android Dialog中SeekBar的使用方法
  7. android 指纹验证api
  8. android APP响应H5页面的点击事件(JS交互)
  9. Android - 自定义标题栏(TitleBar)
  10. Android(安卓)高德定位展示当前位置在地