Home > Android > FlowLayout in Android

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.. 😉 ..!!!

Categories: Android Tags: , ,
  1. karthic vs
    February 17, 2011 at 6:24 am

    Hai can u send sample code for how to add images in this flowlayout
    by progammatically.

  2. karthic vs
    February 17, 2011 at 6:28 am

    i am getting classcastException in line 60,can u suggest any solution.

    Advance Thanks

    • February 18, 2011 at 2:31 am

      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);

  3. Tarun
    April 24, 2011 at 5:21 am

    Thank you!! That works great!!!

  4. ant
    June 9, 2011 at 10:05 am

    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

  5. July 1, 2011 at 12:06 pm

    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.

  6. September 16, 2011 at 11:41 am

    That is great.

  7. Andreas
    October 25, 2011 at 9:24 pm

    Really great work, man!
    Thanx a lot !!

  8. Bob
    November 6, 2011 at 12:38 pm
    • November 7, 2011 at 3:12 pm

      yes

      i modified a little according to my needs

  9. Zori
    November 29, 2011 at 8:52 pm

    Thanks, worked great

  10. simon
    December 2, 2011 at 2:30 pm

    Wouldn’t it be better if it extended a AbsListView in order to use a ListAdapter ?

  11. acs
    December 30, 2011 at 8:20 pm

    Plagiarism or not. I understood this version (and not the apparent original)
    It also worked perfectly first time for my button menu.
    Many Thanks

    • December 31, 2011 at 5:30 am

      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.

  12. Khurram
    January 27, 2012 at 4:00 pm

    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?

  13. February 3, 2012 at 9:28 pm

    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()

    }

    • February 6, 2012 at 3:34 pm

      Thank you, but your posted corrupted source code , and its hard to fix it. looks like some characters are missing.

  14. cutelyaware
    March 13, 2012 at 3:46 am

    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.

    • March 13, 2012 at 5:11 pm

      in wordpress write your code block in

      [ sourcecode language="java" ] [ /sourcecode ]

      for java use language=”java”
      for xml use language=”xml”

      remove spaces

      • cutelyaware
        March 13, 2012 at 8:39 pm

        Good to know, thanks. Now how to edit or delete my past comments to clean up this mess?

  15. Rothariger
    June 25, 2012 at 9:18 pm

    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!

    • June 26, 2012 at 6:20 am

      @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);

      • rothariger
        June 26, 2012 at 10:09 am

        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.

    • June 26, 2012 at 10:54 am

      @Rothariger you have to write in the class where you want to use, in case of listview u can put in viewholder

      • rothariger
        June 26, 2012 at 10:58 am

        The viewholder sounds fine, but anyway that would place any viewholder below the other…

  16. July 6, 2012 at 12:15 am

    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

    • Mathieu
      September 17, 2013 at 9:21 am

      Thanks a lot, this is, by far, the best version I have seen.

  17. Lauren Jett
    July 17, 2012 at 5:26 am

    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?

  18. mixal11
    September 17, 2012 at 11:19 am

    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;
    }
    }
    }
    }
    }

  19. mixal11
    September 17, 2012 at 11:21 am
    • mixal11
      September 17, 2012 at 11:22 am

      Tested with Mono for Android 4.2.5

  20. Matt
    October 6, 2012 at 4:17 pm

    Thanks a ton to everyone who has contributed to making this kickass flowlayout. Works great for me. The android ecosystem/community is so awesome!

  21. June 15, 2013 at 6:27 am

    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

  22. mizo
    August 3, 2013 at 8:29 pm

    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

  23. Neeraj
    September 30, 2013 at 1:21 pm

    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.

  24. ABoukh
    July 30, 2014 at 2:42 am

    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

  25. September 15, 2014 at 1:28 pm

    Whom to thank on my apps “about” section?

  26. September 15, 2014 at 1:38 pm

    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??????

  27. September 16, 2014 at 5:41 pm
  1. April 26, 2012 at 12:00 pm
  2. January 25, 2013 at 7:22 pm
  3. February 3, 2013 at 9:30 pm
  4. October 6, 2013 at 11:00 pm

Leave a reply to ABoukh Cancel reply