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 https://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
Thanks a lot, this is, by far, the best version I have seen.
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!
Magnificent beat ! I wish to apprentice even as you amend
your web site, how can i subscribe for a blog site?
The account aided me a applicable deal. I were tiny bit familiar of
this your broadcast provided vivid transparent concept
thanks for your solution I would like to ask you if I want to make the gravity of the content to the right (the view added to the flowlayout currently from left to right need to change it to right to left )? any thoughts.. thanks
HI, Thanks, it is working. but one problem is coming that when i am adding Button and setting it background color then the space between button goes invisible.and margin and padding is not working.
How can I get the contents of the FlowLayout (which I am adding dynamically) to always be centered on my screen. Currently they are all aligned left…thanks
Whom to thank on my apps “about” section?
http://stackoverflow.com/questions/549451/line-breaking-widget-layout-for-android/560958#560958
Hey, something goes wrong with me. With a blank layout I inserted a button, but when I run the button is now shown. What to do??????
Sorry man, I get other that functioned without issues http://stackoverflow.com/questions/4474237/how-can-i-do-something-like-a-flowlayout-in-android