FlowLayout in Android
This post is linked to previous post click here.
This will help you to create FlowLayout in android
Referred from here
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
/**
*
* @author RAW
*/
public class FlowLayout extends ViewGroup {
private int line_height;
public static class LayoutParams extends ViewGroup.LayoutParams {
public final int horizontal_spacing;
public final int vertical_spacing;
/**
* @param horizontal_spacing Pixels between items, horizontally
* @param vertical_spacing Pixels between items, vertically
*/
public LayoutParams(int horizontal_spacing, int vertical_spacing) {
super(0, 0);
this.horizontal_spacing = horizontal_spacing;
this.vertical_spacing = vertical_spacing;
}
}
public FlowLayout(Context context) {
super(context);
}
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
assert (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED);
final int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingTop() - getPaddingBottom();
final int count = getChildCount();
int line_height = 0;
int xpos = getPaddingLeft();
int ypos = getPaddingTop();
int childHeightMeasureSpec;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
} else {
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
}
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
child.measure(MeasureSpec.makeMeasureSpec(width, MeasureSpec.AT_MOST), childHeightMeasureSpec);
final int childw = child.getMeasuredWidth();
line_height = Math.max(line_height, child.getMeasuredHeight() + lp.vertical_spacing);
if (xpos + childw > width) {
xpos = getPaddingLeft();
ypos += line_height;
}
xpos += childw + lp.horizontal_spacing;
}
}
this.line_height = line_height;
if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
height = ypos + line_height;
} else if (MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
if (ypos + line_height < height) {
height = ypos + line_height;
}
}
setMeasuredDimension(width, height);
}
@Override
protected ViewGroup.LayoutParams generateDefaultLayoutParams() {
return new LayoutParams(1, 1); // default of 1px spacing
}
@Override
protected boolean checkLayoutParams(ViewGroup.LayoutParams p) {
if (p instanceof LayoutParams) {
return true;
}
return false;
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int count = getChildCount();
final int width = r - l;
int xpos = getPaddingLeft();
int ypos = getPaddingTop();
for (int i = 0; i < count; i++) {
final View child = getChildAt(i);
if (child.getVisibility() != GONE) {
final int childw = child.getMeasuredWidth();
final int childh = child.getMeasuredHeight();
final LayoutParams lp = (LayoutParams) child.getLayoutParams();
if (xpos + childw > width) {
xpos = getPaddingLeft();
ypos += line_height;
}
child.layout(xpos, ypos, xpos + childw, ypos + childh);
xpos += childw + lp.horizontal_spacing;
}
}
}
}
Here the xml file.
/* you must write your package name and class name */
<org.android.FlowLayout
android:id="@+id/flow_layout"
android:layout_marginLeft="5dip"
android:layout_width="fill_parent"
android:layout_height="wrap_content"/>
This is very useful while creating bubble.
Enjoy..
..!!!


Hai can u send sample code for how to add images in this flowlayout
by progammatically.
i will try.
i am getting classcastException in line 60,can u suggest any solution.
Advance Thanks
thats because u have not given a proper casting.
try this,
import yourPackageName.FlowLayout.LayoutParams;
LayoutParams flowLP = new LayoutParams(5, 5);
flowlayout.addView(u’r View, flowLP);
Thank you!! That works great!!!
Hai, thank youf for you code but Why i cant see the FlowLayout FlowLayout object flowlayout = (FlowLayout) findViewById(R.id.flow_layout); i cant see the flow_layout in the ids
I’ve got the problem that the layout seems to be calculated correctly (the reserved space seems reasonable), but my childs are not visible. Their onDraw() method never gets called.
The same childs in a LinearLayout are being displayed correctly, albeit only in one line.
That is great.
Really great work, man!
Thanx a lot !!
Isn’t this just plagiarised from this one: http://stackoverflow.com/questions/549451/line-breaking-widget-layout-for-android/560958#560958
yes
i modified a little according to my needs
Thanks, worked great
Wouldn’t it be better if it extended a AbsListView in order to use a ListAdapter ?
Plagiarism or not. I understood this version (and not the apparent original)
It also worked perfectly first time for my button menu.
Many Thanks
The original was perfect, but it didn’t meet my needs so modified a little.
At that time I didn’t had link to the original post so can’t able to mention.
Hello, my problem with the flowlayout is if it is a listviewitem in a listview. If you use the convertView to recycle a flowlayout view group it appears that the children are no longer laid out properly, any advice?
It’s always good to give proper citation. Not just to recognize the work of others but also as a way for you to find your way back later. Anyway, I appreciate the utility and worked it a bit myself to make it a little easier to use. Mainly I just removed the require LayoutParams subclass that was making it difficult for me to use. The child views can have their own padding, insets, etc. so it didn’t seem that important. Here is the resulting code:
package com.superliminal.android.util;
import android.content.Context;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
/**
* A view container with layout behavior like that of the Swing FlowLayout.
* Originally from http://nishantvnair.wordpress.com/2010/09/28/flowlayout-in-android/
*
* @author Melinda Green
*/
public class FlowLayout extends ViewGroup {
private final static int PAD_H = 0, PAD_V = 0; // Space between child views.
private int mHeight;
public FlowLayout(Context context) {
super(context);
}
public FlowLayout(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
assert (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED);
final int width = MeasureSpec.getSize(widthMeasureSpec) – getPaddingLeft() – getPaddingRight();
int height = MeasureSpec.getSize(heightMeasureSpec) – getPaddingTop() – getPaddingBottom();
final int count = getChildCount();
int xpos = getPaddingLeft();
int ypos = getPaddingTop();
int childHeightMeasureSpec;
if(MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST)
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height, MeasureSpec.AT_MOST);
else
childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);
mHeight = 0;
for(int i = 0; i width) {
xpos = getPaddingLeft();
ypos += mHeight;
}
xpos += childw + PAD_H;
}
}
if(MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.UNSPECIFIED) {
height = ypos + mHeight;
} else if(MeasureSpec.getMode(heightMeasureSpec) == MeasureSpec.AT_MOST) {
if(ypos + mHeight < height) {
height = ypos + mHeight;
}
}
setMeasuredDimension(width, height);
} // end onMeasure()
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
final int width = r – l;
int xpos = getPaddingLeft();
int ypos = getPaddingTop();
for(int i = 0; i width) {
xpos = getPaddingLeft();
ypos += mHeight;
}
child.layout(xpos, ypos, xpos + childw, ypos + childh);
xpos += childw + PAD_H;
}
}
} // end onLayout()
}
Thank you, but your posted corrupted source code , and its hard to fix it. looks like some characters are missing.
Well that was unfortunate. WordPress removed bits of text and I couldn’t find any ways to either edit my post or figure out how to make it take the code verbatim. Here is a link to my version on my web site:
http://www.superliminal.com/sources/FlowLayout.java.html
whre I *can* control the formatting.
in wordpress write your code block in
for java use language=”java”
for xml use language=”xml”
remove spaces
Good to know, thanks. Now how to edit or delete my past comments to clean up this mess?
hi, im a noob in android development, i want to know if theres a way of using this in a gridview or a listview?
and another thing i cant fix the classcastexception.
thanks!
@Rothariger
I have not tried it with list view, i hope it will work.
for class cast exception
try this,
import yourPackageName.FlowLayout.LayoutParams;
LayoutParams flowLP = new LayoutParams(5, 5);
flowlayout.addView(u’r View, flowLP);
I have see that before, but i don’t know where to put that addview.
Well actually it does work in gridview or listview but is not working as expected the children aren’t added side by side till the line is full.
Thanks for your time.
@Rothariger you have to write in the class where you want to use, in case of listview u can put in viewholder
The viewholder sounds fine, but anyway that would place any viewholder below the other…
If you are interested. FlowLayout works great! Thank you for the work! I fixed some small bugs:
- If you have different line heights, it will use the same line height for every line
- wrap_content does not work
I fixed them in this version: https://gist.github.com/3057258
I am using this layout to display many buttons that I dynamically add – The buttons fill up my entire screen (which I want) – I just need to make the screen scrollable, but when I try to add the flowlayout view to a scroll view, my program crashes – any ideas on how to get this to scroll?
c# version:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Util;
using Android.Views;
using Android.Widget;
namespace Bzing.Client.Droid.UserControls
{
public class FlowLayout : ViewGroup
{
private int line_height;
public class LayoutParams : ViewGroup.LayoutParams
{
public readonly int horizontal_spacing;
public readonly int vertical_spacing;
/**
* @param horizontal_spacing Pixels between items, horizontally
* @param vertical_spacing Pixels between items, vertically
*/
public LayoutParams(int horizontalSpacing, int verticalSpacing)
: base(0, 0)
{
this.horizontal_spacing = horizontalSpacing;
this.vertical_spacing = verticalSpacing;
}
}
public FlowLayout(Context context, IAttributeSet attrs) :
base(context, attrs)
{
Initialize();
}
private void Initialize()
{
}
protected override void OnMeasure(int widthMeasureSpec, int heightMeasureSpec)
{
//assert (MeasureSpec.getMode(widthMeasureSpec) != MeasureSpec.UNSPECIFIED);
int width = MeasureSpec.GetSize(widthMeasureSpec) – PaddingLeft – PaddingRight;
int height = MeasureSpec.GetSize(heightMeasureSpec) – PaddingTop – PaddingBottom;
int count = ChildCount;
int line_height = 0;
int xpos = PaddingLeft;
int ypos = PaddingTop;
int childHeightMeasureSpec;
if (MeasureSpec.GetMode(heightMeasureSpec) == MeasureSpecMode.AtMost)
{
childHeightMeasureSpec = MeasureSpec.MakeMeasureSpec(height, MeasureSpecMode.AtMost);
}
else
{
childHeightMeasureSpec = MeasureSpec.MakeMeasureSpec(0, MeasureSpecMode.Unspecified);
}
for (int i = 0; i width)
{
xpos = PaddingLeft;
ypos += line_height;
}
xpos += childw + lp.horizontal_spacing;
}
}
this.line_height = line_height;
if (MeasureSpec.GetMode(heightMeasureSpec) == MeasureSpecMode.Unspecified)
{
height = ypos + line_height;
}
else if (MeasureSpec.GetMode(heightMeasureSpec) == MeasureSpecMode.AtMost)
{
if (ypos + line_height < height)
{
height = ypos + line_height;
}
}
SetMeasuredDimension(width, height);
}
protected override ViewGroup.LayoutParams GenerateDefaultLayoutParams()
{
return new LayoutParams(1, 1); // default of 1px spacing
}
protected override bool CheckLayoutParams(ViewGroup.LayoutParams p)
{
if (p is LayoutParams)
{
return true;
}
return false;
}
protected override void OnLayout(bool changed, int l, int t, int r, int b)
{
int count = ChildCount;
int width = r – l;
int xpos = PaddingLeft;
int ypos = PaddingTop;
for (int i = 0; i width)
{
xpos = PaddingLeft;
ypos += line_height;
}
child.Layout(xpos, ypos, xpos + childw, ypos + childh);
xpos += childw + lp.horizontal_spacing;
}
}
}
}
}
or Gist version: https://gist.github.com/3736751
Tested with Mono for Android 4.2.5
Thanks a ton to everyone who has contributed to making this kickass flowlayout. Works great for me. The android ecosystem/community is so awesome!