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

        先看最终效果

android流式布局热门标签的实现_第1张图片

自定义流式布局的实现

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. Android 自定义View及其在布局文件中的使用示例(三):结合Android
  2. 关于相对布局RelativeLayout的各种属性介绍
  3. Android布局(相对布局)
  4. Android 众多的布局属性详解
  5. LinearLayout布局实现垂直水平居中
  6. Android RelativeLayout 相对布局解析
  7. Android学习笔记(11)---关于布局的一些小事
  8. Android布局中的常用属性小结

随机推荐

  1. 美国621位经济学家关于支持就业和企业应
  2. 我是如何从一个诗人变成一个计量实证高手
  3. 对所有国内学者开放的顶级计量经济学云端
  4. 第一(二)卷.Stata最新且有趣的程序系列汇
  5. 第一篇博客
  6. 如何选择正确的因变量(控制变量),让你的计
  7. 儿时环境对其人生长远影响的综述, 包括前
  8. 他们只有本硕学历, 却发过了AER, JPE, QJ
  9. 气候经济学能发Nature,Science的三大热点
  10. nature首次出现经济学编辑!想发nature的学