在日常的app使用中,我们会在android 的app中看见热门标签等自动换行的流式布局,今天就为大家分享一种android流式布局的实现。

        先看最终效果

自定义流式布局的实现

package com.sunny.flowlayout.view;import java.util.ArrayList;import java.util.List;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;public class FlowLayout extends ViewGroup {public FlowLayout(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public FlowLayout(Context context, AttributeSet attrs) {this(context, attrs, 0);}public FlowLayout(Context context) {this(context, null);}@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);int modeWidth = MeasureSpec.getMode(widthMeasureSpec);int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);int modeHeight = MeasureSpec.getMode(heightMeasureSpec);// wrap_contentint width = 0;int height = 0;// 记录每一行的宽度与高度int lineWidth = 0;int lineHeight = 0;// 得到内部元素的个数int cCount = getChildCount();for (int i = 0; i < cCount; i++) {View child = getChildAt(i);// 测量子View的宽和高measureChild(child, widthMeasureSpec, heightMeasureSpec);// 得到LayoutParamsMarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();// 子View占据的宽度int childWidth = child.getMeasuredWidth() + lp.leftMargin+ lp.rightMargin;// 子View占据的高度int childHeight = child.getMeasuredHeight() + lp.topMargin+ lp.bottomMargin;// 换行if (lineWidth + childWidth > sizeWidth - getPaddingLeft()- getPaddingRight()) {// 对比得到最大的宽度width = Math.max(width, lineWidth);// 重置lineWidthlineWidth = childWidth;// 记录行高height += lineHeight;lineHeight = childHeight;} else// 未换行{// 叠加行宽lineWidth += childWidth;// 得到当前行最大的高度lineHeight = Math.max(lineHeight, childHeight);}// 最后一个控件if (i == cCount - 1) {width = Math.max(lineWidth, width);height += lineHeight;}}setMeasuredDimension(modeWidth == MeasureSpec.EXACTLY ? sizeWidth : width+ getPaddingLeft() + getPaddingRight(),modeHeight == MeasureSpec.EXACTLY ? sizeHeight : height+ getPaddingTop() + getPaddingBottom()//);}/** * 存储所有的View */private List> mAllViews = new ArrayList>();/** * 每一行的高度 */private List mLineHeight = new ArrayList();@Overrideprotected void onLayout(boolean changed, int l, int t, int r, int b) {mAllViews.clear();mLineHeight.clear();// 当前ViewGroup的宽度int width = getWidth();int lineWidth = 0;int lineHeight = 0;List lineViews = new ArrayList();int cCount = getChildCount();for (int i = 0; i < cCount; i++) {View child = getChildAt(i);MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();int childWidth = child.getMeasuredWidth();int childHeight = child.getMeasuredHeight();// 如果需要换行     if (childWidth + lineWidth + lp.leftMargin + lp.rightMargin > width- getPaddingLeft() - getPaddingRight()) {// 记录LineHeightmLineHeight.add(lineHeight);// 记录当前行的ViewsmAllViews.add(lineViews);// 重置我们的行宽和行高lineWidth = 0;lineHeight = childHeight + lp.topMargin + lp.bottomMargin;// 重置我们的View集合lineViews = new ArrayList();}lineWidth += childWidth + lp.leftMargin + lp.rightMargin;lineHeight = Math.max(lineHeight, childHeight + lp.topMargin+ lp.bottomMargin);lineViews.add(child);}// for end// 处理最后一行mLineHeight.add(lineHeight);mAllViews.add(lineViews);// 设置子View的位置int left = getPaddingLeft();int top = getPaddingTop();// 行数int lineNum = mAllViews.size();for (int i = 0; i < lineNum; i++) {// 当前行的所有的ViewlineViews = mAllViews.get(i);lineHeight = mLineHeight.get(i);for (int j = 0; j < lineViews.size(); j++) {View child = lineViews.get(j);// 判断child的状态if (child.getVisibility() == View.GONE) {continue;}MarginLayoutParams lp = (MarginLayoutParams) child.getLayoutParams();int lc = left + lp.leftMargin;int tc = top + lp.topMargin;int rc = lc + child.getMeasuredWidth();int bc = tc + child.getMeasuredHeight();// 为子View进行布局child.layout(lc, tc, rc, bc);left += child.getMeasuredWidth() + lp.leftMargin+ lp.rightMargin;}left = getPaddingLeft();top += lineHeight;}}/** * 与当前ViewGroup对应的LayoutParams */@Overridepublic LayoutParams generateLayoutParams(AttributeSet attrs) {return new MarginLayoutParams(getContext(), attrs);}}

         流式布局代码实现的注释还算比较详细,请参考具体代码及注释说明。

流式布局xml文件

        

主页面Activity的实现

package com.sunny.flowlayout;import com.sunny.flowlayout.view.FlowLayout;import android.R.mipmap;import android.os.Bundle;import android.app.ActionBar.LayoutParams;import android.app.Activity;import android.view.LayoutInflater;import android.view.Menu;import android.view.ViewGroup.MarginLayoutParams;import android.widget.Button;import android.widget.TextView;public class FlowLayoutActivity extends Activity {private FlowLayout mFlowLayout;private String[] mVals =new String[]{       "Hello","Android","Welcome","Music","Sport","Working","Game","Fishing","Shopping","Music Singing","Sport happy","Working Hard","Game Team","Fishing river","Shopping more"};@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_flow_layout);mFlowLayout = (FlowLayout) findViewById(R.id.id_flowlayout);initData();}//初始化数据public void initData(){LayoutInflater mInflater = LayoutInflater.from(this);for (int i = 0; i < mVals.length; i++) {        TextView tv = (TextView) mInflater.inflate(R.layout.tv, mFlowLayout, false);tv.setText(mVals[i]);mFlowLayout.addView(tv);}}}

TextView布局xml文件

<?xml version="1.0" encoding="utf-8"?>

TextView设置背景样式

<?xml version="1.0" encoding="utf-8"?>            

    今天是第一次写博客,今天是开始,我会一直坚持下去,欢迎大家一块交流学习

    

更多相关文章

  1. ImageView的android:maxHeight,android:minHeight的正确设置
  2. ConstraintLayout子View android:minHeight 无效解决
  3. ImageView的android:maxHeight,android:minHeight的正确设置
  4. android main.xml分析。。一点点补充
  5. Android实现九宫格 主界面应用列表效果
  6. Android(安卓)中自定义View(三)
  7. Android(安卓)中文 API (16) ―― AnalogClock
  8. android九宫格
  9. Android设计尺寸规范--Android(安卓)Design Guidelines

随机推荐

  1. 文字跑马灯
  2. Android 9.0 Launcher源码分析(三)——Laun
  3. android button 正常状态,按下状态
  4. BitmapFactory.Options学习笔记
  5. Android的Context简介
  6. Android中的一些开关
  7. Android Studio之安卓学习布局管理器
  8. [android]控件Button常用属性
  9. Android(安卓)NIO简易聊天室
  10. android属性