代码:流式布局FlowLayout

1.代码:

package extra.view;

import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.view.ViewGroup;

import java.util.ArrayList;import java.util.List;

public class FlowLayout extends ViewGroup{

private static final String TAG = "FlowLayout";

public FlowLayout(Context context, AttributeSet attrs)   {      super(context, attrs);   }

@Override   protected LayoutParams generateLayoutParams(         LayoutParams p)   {      return new MarginLayoutParams(p);   }

@Override   public LayoutParams generateLayoutParams(AttributeSet attrs)   {      return new MarginLayoutParams(getContext(), attrs);   }

@Override   protected LayoutParams generateDefaultLayoutParams()   {      return new MarginLayoutParams(LayoutParams.MATCH_PARENT,            LayoutParams.MATCH_PARENT);   }

/**    * 负责设置子控件的测量模式和大小 根据所有子控件设置自己的宽和高    */   @Override   protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)   {      super.onMeasure(widthMeasureSpec, heightMeasureSpec);      // 获得它的父容器为它设置的测量模式和大小      int sizeWidth = MeasureSpec.getSize(widthMeasureSpec);      int sizeHeight = MeasureSpec.getSize(heightMeasureSpec);      int modeWidth = MeasureSpec.getMode(widthMeasureSpec);      int modeHeight = MeasureSpec.getMode(heightMeasureSpec);

Log.e(TAG, sizeWidth + "," + sizeHeight);

// 如果是warp_content情况下,记录宽和高      int width = 0;      int height = 0;      /**       * 记录每一行的宽度,width不断取最大宽度       */      int lineWidth = 0;      /**       * 每一行的高度,累加至height       */      int lineHeight = 0;

int cCount = getChildCount();

// 遍历每个子元素      for (int i = 0; i < cCount; i++)      {         View child = getChildAt(i);         // 测量每一个child的宽和高         measureChild(child, widthMeasureSpec, heightMeasureSpec);         // 得到child的lp         MarginLayoutParams lp = (MarginLayoutParams) child               .getLayoutParams();         // 当前子空间实际占据的宽度         int childWidth = child.getMeasuredWidth() + lp.leftMargin               + lp.rightMargin;         // 当前子空间实际占据的高度         int childHeight = child.getMeasuredHeight() + lp.topMargin               + lp.bottomMargin;         /**          * 如果加入当前child,则超出最大宽度,则的到目前最大宽度给width,类加height 然后开启新行          */         if (lineWidth + childWidth > sizeWidth)         {            width = Math.max(lineWidth, childWidth);// 取最大的            lineWidth = childWidth; // 重新开启新行,开始记录            // 叠加当前高度,            height += lineHeight;            // 开启记录下一行的高度            lineHeight = childHeight;         } else         // 否则累加值lineWidth,lineHeight取最大高度         {            lineWidth += childWidth;            lineHeight = Math.max(lineHeight, childHeight);         }         // 如果是最后一个,则将当前记录的最大宽度和当前lineWidth做比较         if (i == cCount - 1)         {            width = Math.max(width, lineWidth);            height += lineHeight;         }

}      setMeasuredDimension((modeWidth == MeasureSpec.EXACTLY) ? sizeWidth            : width, (modeHeight == MeasureSpec.EXACTLY) ? sizeHeight            : height);

}   /**    * 存储所有的View,按行记录    */   private List<List<View>> mAllViews = new ArrayList<List<View>>();   /**    * 记录每一行的最大高度    */   private List<Integer> mLineHeight = new ArrayList<Integer>();   @Override   protected void onLayout(boolean changed, int l, int t, int r, int b)   {      mAllViews.clear();      mLineHeight.clear();

int width = getWidth();

int lineWidth = 0;      int lineHeight = 0;      // 存储每一行所有的childView      List<View> lineViews = new ArrayList<View>();      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 + lp.leftMargin + lp.rightMargin + lineWidth > width)         {            // 记录这一行所有的View以及最大高度            mLineHeight.add(lineHeight);            // 将当前行的childView保存,然后开启新的ArrayList保存下一行的childView            mAllViews.add(lineViews);            lineWidth = 0;// 重置行宽            lineViews = new ArrayList<View>();         }         /**          * 如果不需要换行,则累加          */         lineWidth += childWidth + lp.leftMargin + lp.rightMargin;         lineHeight = Math.max(lineHeight, childHeight + lp.topMargin               + lp.bottomMargin);         lineViews.add(child);      }      // 记录最后一行      mLineHeight.add(lineHeight);      mAllViews.add(lineViews);

int left = 0;      int top = 0;      // 得到总行数      int lineNums = mAllViews.size();      for (int i = 0; i < lineNums; i++)      {         // 每一行的所有的views         lineViews = mAllViews.get(i);         // 当前行的最大高度         lineHeight = mLineHeight.get(i);

Log.e(TAG, "第" + i + "行 :" + lineViews.size() + " , " + lineViews);         Log.e(TAG, "第" + i + "行, :" + lineHeight);

// 遍历当前行所有的View         for (int j = 0; j < lineViews.size(); j++)         {            View child = lineViews.get(j);            if (child.getVisibility() == View.GONE)            {               continue;            }            MarginLayoutParams lp = (MarginLayoutParams) child                  .getLayoutParams();

//计算childView的left,top,right,bottom            int lc = left + lp.leftMargin;            int tc = top + lp.topMargin;            int rc =lc + child.getMeasuredWidth();            int bc = tc + child.getMeasuredHeight();

Log.e(TAG, child + " , l = " + lc + " , t = " + t + " , r ="                  + rc + " , b = " + bc);

child.layout(lc, tc, rc, bc);

left += child.getMeasuredWidth() + lp.rightMargin                  + lp.leftMargin;         }         left = 0;         top += lineHeight;      }

}}

来自为知笔记(Wiz)

时间: 2024-10-27 00:43:12

代码:流式布局FlowLayout的相关文章

Android之自定义流式布局FlowLayout

流式布局常常用于“热门标签”中,大概功能就是将所有的子View一行一行的排列,如果一行中剩下的空间不足以盛放下一个子View,则换到另一行继续排列.这样做的好处是不需要在主线程中自己麻烦定义控件的位置,只需要把生成的控件放到容器中,容器自己会自动排列.首先来看一下运行结果: Android中的自定义容器控件(继承自ViewGroup的控件)都有两个必须实现的方法:onMeasure()和onLayout() (1)onMeasure:测量子View的宽和高,设置自己的宽和高,根据自View的布局

Java图形化界面设计——布局管理器之FlowLayout(流式布局)

一.布局管理器所属类包 所属类包 布局管理器名称 说明 Java.awt FlowLayout(流式布局) 组件按照加入的先后顺序按照设置的对齐方式从左向右排列,一行排满到下一行开始继续排列 BorderLayout(边界布局) 容器划分为东.西.南.北.中五个区域,每个区域只能放置一个组件. GridLayout(网格布局) 容器的空间划分成M×N列的网格区域, 每个区域只能放置一个组件. CardLayout(卡片布局) 如同一叠牌,每个牌对应一个组件,但每次只能显示其中的一张牌.适用于在一

转:Java图形化界面设计——布局管理器之FlowLayout(流式布局)其他请参考转载出处网址

http://blog.csdn.net/liujun13579/article/details/7771191 前文讲解了JFrame.JPanel,其中已经涉及到了空布局的使用.Java虽然可以以像素为单位对组件进行精确的定位,但是其在不同的系统中将会有一定的显示差异,使得显示效果不尽相同,为此java提供了布局管理器,以使编写的图形界面具有良好的平台无关性. 注意:所有的布局管理器均是针对容器来使用的,包括顶层容器和中间容器. 一.布局管理器所属类包 所属类包 布局管理器名称 说明 Jav

03 Java图形化界面设计&mdash;&mdash;布局管理器之FlowLayout(流式布局)

前文讲解了JFrame.JPanel,其中已经涉及到了空布局的使用.Java虽然可以以像素为单位对组件进行精确的定位,但是其在不同的系统中将会有一定的显示差异,使得显示效果不尽相同,为此java提供了布局管理器,以使编写的图形界面具有良好的平台无关性. 注意:所有的布局管理器均是针对容器来使用的,包括顶层容器和中间容器. 一.布局管理器所属类包 所属类包 布局管理器名称 说明 Java.awt FlowLayout(流式布局) 组件按照加入的先后顺序按照设置的对齐方式从左向右排列,一行排满到下一

GUI布局:边界布局、流式布局、网格布局、卡片布局

边界布局 package guiTest; //JFrame默认的是边界布局BorderLayout import java.awt.BorderLayout; import javax.swing.JButton; import javax.swing.JFrame; public class BorderLayoutDemo { public static void main(String[] args) { JFrame f = new JFrame("边界布局BorderLayout&q

JAVA 流式布局管理器

//流式布局管理器 import java.awt.*; import javax.swing.*; public class Jiemian2 extends JFrame{ //定义组件 JButton[] an = {null,null,null,null,null,null,null,null}; public static void main(String[] args){ //运行本类的构造方法 Jiemian2 jiemian = new Jiemian2(); } public

android流式布局热门标签的实现

在日常的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 an

Android中常见的热门标签的流式布局的实现

一.概述:在日常的app使用中,我们会在android 的app中看见 热门标签等自动换行的流式布局,今天,我们就来看看如何 自定义一个类似热门标签那样的流式布局吧(源码下载在下面最后给出) 类似的自定义布局.下面我们就来详细介绍流式布局的应用特点以及用的的技术点: 1.流式布局的特点以及应用场景    特点:当上面一行的空间不够容纳新的TextView时候,    才开辟下一行的空间 原理图: 场景:主要用于关键词搜索或者热门标签等场景2.自定义ViewGroup,重点重写下面两个方法 1.o

自定义ViewGroup 流式布局

使用 public class MainActivity extends Activity {     @Override     protected void onCreate(Bundle savedInstanceState) {         super.onCreate(savedInstanceState);         setContentView(R.layout.activity_flowlayout);         FlowLayout flow_layout =