自定义自动换行布局控件,实现子控件宽度超出整行时自动换行。setMeasuredDimension的使用

来源:互联网 发布:让其响彻mmd动作数据 编辑:程序博客网 时间:2024/05/29 06:46

在开发应用时,很多时候都遇到动态加载标签,但是内容不确定的情况,常用的几种布局在此时就不太好用了,如LinearLayout只能单行或者单列进行布局,而RelativeLayout在定位时需要确定子控件的大小和相对位置,因此需要自己进行一些重写来实现自行换行。

public class FlowLayout extends RelativeLayout {        int mLeft, mRight, mTop, mBottom, currentBottom;        Hashtable<View, Position> map = new Hashtable<View, FlowLayout.Position>();                public FlowLayout(Context context, AttributeSet attrs, int defStyle) {                super(context, attrs, defStyle);        }        public FlowLayout(Context context, AttributeSet attrs) {                super(context, attrs);        }        public FlowLayout(Context context) {                super(context);        }        @Override        protected void onLayout(boolean changed, int l, int t, int r, int b) {                // TODO Auto-generated method stub                int count = getChildCount();                for (int i = 0; i < count; i++) {                        View child = getChildAt(i);                        Position pos = map.get(child);                        if (pos != null) {                                child.layout(pos.left, pos.top, pos.right, pos.bottom);                        } else {                                Log.i("MyLayout", "error");                        }                }        }        public int getPosition(int IndexInRow, int childIndex) {                if (IndexInRow > 0) {                        return getPosition(IndexInRow - 1, childIndex - 1)                                        + getChildAt(childIndex - 1).getMeasuredWidth()+10;                }                return 0;        }        @Override        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {                // TODO Auto-generated method stub                super.onMeasure(widthMeasureSpec, heightMeasureSpec);                int width = MeasureSpec.getSize(widthMeasureSpec);                mLeft = 0;                mRight = 0;                mTop = 0;                mBottom = 0;                int j = 0;                int count = getChildCount();                for (int i = 0; i < count; i++) {                        Position position = new Position();                        View view = getChildAt(i);                        mLeft = getPosition(i - j, i);                        mRight = mLeft + view.getMeasuredWidth();                        if (mRight >= width) {                                j = i;                                mLeft = getPosition(i - j, i);                                mRight = mLeft + view.getMeasuredWidth();                                mTop += getChildAt(i).getMeasuredHeight()+5;                        }                        mBottom = mTop + view.getMeasuredHeight();                        position.left = mLeft;                        position.top = mTop;                        position.right = mRight;                        position.bottom = mBottom;                        map.put(view, position);                }                setMeasuredDimension(width, mBottom);        }        private class Position {                int left, top, right, bottom;        }}

如以上代码,在测量大小时,我们把所有的子控件大小都测量出来,然后保存起来等待onlayout的时候直接使用,防止屏幕脏屏,显示混乱。

而红色的代码是很重要的,现计算时算出布局文件的大小,防止只显示一行内容或者显示不全的问题。


在布局时,当做RelativeLayout使用即可,xml文件此处不再进行详细说明!

为布局添加子控件时,代码如下:


……String[] contacts = yourgetMethod();FlowLayout contacts = (FlowLayout)findViewById(R.id.contacts);contacts.removeAllViewsInLayout();for (int i=0;i<contacts.length;i++) {TextView tv = new TextView(this);tv.setTextSize(15);……tv.setText(contacts[i]);contacts.add(tv);}……


原创粉丝点击