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

来源:互联网 发布:故宫 淘宝 哪个 编辑:程序博客网 时间:2024/05/17 01:34

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

[java] view plaincopy
  1. public class FlowLayout extends RelativeLayout {  
  2.         int mLeft, mRight, mTop, mBottom, currentBottom;  
  3.         Hashtable<View, Position> map = new Hashtable<View, FlowLayout.Position>();  
  4.   
  5.           
  6.         public FlowLayout(Context context, AttributeSet attrs, int defStyle) {  
  7.                 super(context, attrs, defStyle);  
  8.   
  9.         }  
  10.   
  11.         public FlowLayout(Context context, AttributeSet attrs) {  
  12.                 super(context, attrs);  
  13.   
  14.         }  
  15.   
  16.         public FlowLayout(Context context) {  
  17.                 super(context);  
  18.   
  19.         }  
  20.   
  21.         @Override  
  22.         protected void onLayout(boolean changed, int l, int t, int r, int b) {  
  23.                 // TODO Auto-generated method stub  
  24.                 int count = getChildCount();  
  25.                 for (int i = 0; i < count; i++) {  
  26.                         View child = getChildAt(i);  
  27.                         Position pos = map.get(child);  
  28.                         if (pos != null) {  
  29.                                 child.layout(pos.left, pos.top, pos.right, pos.bottom);  
  30.                         } else {  
  31.                                 Log.i("MyLayout""error");  
  32.                         }  
  33.                 }  
  34.   
  35.         }  
  36.   
  37.         public int getPosition(int IndexInRow, int childIndex) {  
  38.                 if (IndexInRow > 0) {  
  39.                         return getPosition(IndexInRow - 1, childIndex - 1)  
  40.                                         + getChildAt(childIndex - 1).getMeasuredWidth()+10;  
  41.                 }  
  42.                 return 0;  
  43.         }  
  44.   
  45.         @Override  
  46.         protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  47.                 // TODO Auto-generated method stub  
  48.                 super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  49.                 int width = MeasureSpec.getSize(widthMeasureSpec);  
  50.                 mLeft = 0;  
  51.                 mRight = 0;  
  52.                 mTop = 0;  
  53.                 mBottom = 0;  
  54.                 int j = 0;  
  55.                 int count = getChildCount();  
  56.                 for (int i = 0; i < count; i++) {  
  57.                         Position position = new Position();  
  58.                         View view = getChildAt(i);  
  59.                         mLeft = getPosition(i - j, i);  
  60.                         mRight = mLeft + view.getMeasuredWidth();  
  61.                         if (mRight >= width) {  
  62.                                 j = i;  
  63.                                 mLeft = getPosition(i - j, i);  
  64.                                 mRight = mLeft + view.getMeasuredWidth();  
  65.                                 mTop += getChildAt(i).getMeasuredHeight()+5;  
  66.                         }  
  67.                         mBottom = mTop + view.getMeasuredHeight();  
  68.                         position.left = mLeft;  
  69.                         position.top = mTop;  
  70.                         position.right = mRight;  
  71.                         position.bottom = mBottom;  
  72.                         map.put(view, position);  
  73.                 }  
  74.                 <span style="color:#FF0000;">setMeasuredDimension(width, mBottom);</span>  
  75.         }  
  76.   
  77.         private class Position {  
  78.                 int left, top, right, bottom;  
  79.         }  
  80.   
  81. }  

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

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


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

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


[java] view plaincopy
  1. ……  
  2. String[] contacts = yourgetMethod();  
  3. FlowLayout contacts = (FlowLayout)findViewById(R.id.contacts);  
  4. contacts.removeAllViewsInLayout();  
  5. for (int i=0;i<contacts.length;i++) {  
  6.     TextView tv = new TextView(this);  
  7.     tv.setTextSize(15);  
  8.     ……  
  9.     tv.setText(contacts[i]);  
  10.     contacts.add(tv);  
  11. }  
  12. ……  
0 0