1.TextView的样式
1 <?xml version="1.0" encoding="utf-8"?> 2 <shape xmlns:android="http://schemas.android.com/apk/res/android" > 3 <solid android:color="#666666" /> 4 <corners android:radius="10dp" /> 5 <padding 6 android:left="5dp" 7 android:right="5dp" 8 android:top="5dp" 9 android:bottom="5dp" 10 /> 11 12 </shape>
2.main布局
1 <com.example.administrator.liushilayout.XCFlowLayout 2 android:id="@+id/flowlayout" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" > 5 6 </com.example.administrator.liushilayout.XCFlowLayout>
3.自定义ViewGroup
1 public class XCFlowLayout extends ViewGroup{ 2 //存储所有子View 3 private List<List<View>> mAllChildViews = new ArrayList<>(); 4 //每一行的高度 5 private List<Integer> mLineHeight = new ArrayList<>(); 6 7 public XCFlowLayout(Context context) { 8 this(context, null); 9 // TODO Auto-generated constructor stub 10 } 11 public XCFlowLayout(Context context, AttributeSet attrs) { 12 this(context, attrs, 0); 13 // TODO Auto-generated constructor stub 14 } 15 public XCFlowLayout(Context context, AttributeSet attrs, int defStyle) { 16 super(context, attrs, defStyle); 17 // TODO Auto-generated constructor stub 18 } 19 @Override 20 protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) { 21 // TODO Auto-generated method stub 22 23 //父控件传进来的宽度和高度以及对应的测量模式 24 int sizeWidth = MeasureSpec.getSize(widthMeasureSpec); 25 int modeWidth = MeasureSpec.getMode(widthMeasureSpec); 26 int sizeHeight = MeasureSpec.getSize(heightMeasureSpec); 27 int modeHeight = MeasureSpec.getMode(heightMeasureSpec); 28 29 //如果当前ViewGroup的宽高为wrap_content的情况 30 int width = 0;//自己测量的 宽度 31 int height = 0;//自己测量的高度 32 //记录每一行的宽度和高度 33 int lineWidth = 0; 34 int lineHeight = 0; 35 36 //获取子view的个数 37 int childCount = getChildCount(); 38 for(int i = 0;i < childCount; i ++){ 39 View child = getChildAt(i); 40 //测量子View的宽和高 41 measureChild(child, widthMeasureSpec, heightMeasureSpec); 42 //得到LayoutParams 43 MarginLayoutParams lp = (MarginLayoutParams) getLayoutParams(); 44 //子View占据的宽度 45 int childWidth = child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; 46 //子View占据的高度 47 int childHeight = child.getMeasuredHeight() + lp.topMargin + lp.bottomMargin; 48 //换行时候 49 if(lineWidth + childWidth > sizeWidth){ 50 //对比得到最大的宽度 51 width = Math.max(width, lineWidth); 52 //重置lineWidth 53 lineWidth = childWidth; 54 //记录行高 55 height += lineHeight; 56 lineHeight = childHeight; 57 }else{//不换行情况 58 //叠加行宽 59 lineWidth += childWidth; 60 //得到最大行高 61 lineHeight = Math.max(lineHeight, childHeight); 62 } 63 //处理最后一个子View的情况 64 if(i == childCount -1){ 65 width = Math.max(width, lineWidth); 66 height += lineHeight; 67 } 68 } 69 //wrap_content 70 setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width, 71 modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height); 72 super.onMeasure(widthMeasureSpec, heightMeasureSpec); 73 } 74 75 @Override 76 protected void onLayout(boolean changed, int l, int t, int r, int b) { 77 // TODO Auto-generated method stub 78 mAllChildViews.clear(); 79 mLineHeight.clear(); 80 //获取当前ViewGroup的宽度 81 int width = getWidth(); 82 83 int lineWidth = 0; 84 int lineHeight = 0; 85 //记录当前行的view 86 List<View> lineViews = new ArrayList<View>(); 87 int childCount = getChildCount(); 88 for(int i = 0;i < childCount; i ++){ 89 View child = getChildAt(i); 90 MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); 91 int childWidth = child.getMeasuredWidth(); 92 int childHeight = child.getMeasuredHeight(); 93 94 //如果需要换行 95 if(childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width){ 96 //记录LineHeight 97 mLineHeight.add(lineHeight); 98 //记录当前行的Views 99 mAllChildViews.add(lineViews); 100 //重置行的宽高 101 lineWidth = 0; 102 lineHeight = childHeight + lp.topMargin + lp.bottomMargin; 103 //重置view的集合 104 lineViews = new ArrayList(); 105 } 106 lineWidth += childWidth + lp.leftMargin + lp.rightMargin; 107 lineHeight = Math.max(lineHeight, childHeight + lp.topMargin + lp.bottomMargin); 108 lineViews.add(child); 109 } 110 //处理最后一行 111 mLineHeight.add(lineHeight); 112 mAllChildViews.add(lineViews); 113 114 //设置子View的位置 115 int left = 0; 116 int top = 0; 117 //获取行数 118 int lineCount = mAllChildViews.size(); 119 for(int i = 0; i < lineCount; i ++){ 120 //当前行的views和高度 121 lineViews = mAllChildViews.get(i); 122 lineHeight = mLineHeight.get(i); 123 for(int j = 0; j < lineViews.size(); j ++){ 124 View child = lineViews.get(j); 125 //判断是否显示 126 if(child.getVisibility() == View.GONE){ 127 continue; 128 } 129 MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams(); 130 int cLeft = left + lp.leftMargin; 131 int cTop = top + lp.topMargin; 132 int cRight = cLeft + child.getMeasuredWidth(); 133 int cBottom = cTop + child.getMeasuredHeight(); 134 //进行子View进行布局 135 child.layout(cLeft, cTop, cRight, cBottom); 136 left += child.getMeasuredWidth() + lp.leftMargin + lp.rightMargin; 137 } 138 left = 0; 139 top += lineHeight; 140 } 141 142 } 143 /** 144 * 与当前ViewGroup对应的LayoutParams 145 */ 146 @Override 147 public LayoutParams generateLayoutParams(AttributeSet attrs) { 148 // TODO Auto-generated method stub 149 150 return new MarginLayoutParams(getContext(), attrs); 151 } 152 }
4.Ativity实现
1 public class MainActivity extends AppCompatActivity { 2 private String mNames[] = { 3 "welcome","android","TextView", 4 "apple","jamy","kobe bryant", 5 "jordan","layout","viewgroup", 6 "margin","padding","text", 7 "name","type","search","logcat" 8 }; 9 private XCFlowLayout mFlowLayout; 10 @Override 11 protected void onCreate(Bundle savedInstanceState) { 12 super.onCreate(savedInstanceState); 13 setContentView(R.layout.activity_main); 14 15 initChildViews(); 16 17 } 18 private void initChildViews() { 19 // TODO Auto-generated method stub 20 mFlowLayout = (XCFlowLayout) findViewById(R.id.flowlayout); 21 ViewGroup.MarginLayoutParams lp = new ViewGroup.MarginLayoutParams( 22 ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT); 23 lp.leftMargin = 5; 24 lp.rightMargin = 5; 25 lp.topMargin = 5; 26 lp.bottomMargin = 5; 27 for(int i = 0; i < mNames.length; i ++){ 28 TextView view = new TextView(this); 29 view.setText(mNames[i]); 30 view.setTextColor(Color.WHITE); 31 view.setBackgroundDrawable(getResources().getDrawable(R.drawable.shap)); 32 mFlowLayout.addView(view,lp); 33 } 34 } 35 36 }