In May 2016 a new project was pushed to the official Google Github repo named flexbox-layout. It is an Android layout manager which offers similar behaviour to the CSS flexible box layout module. In this series we’ll take a look at FlexboxLayout and try and gain some insights in to how it works and how to get the best out of it.
Before we dive in it is worth mentioning that the format of this series is goiing to be a little different to normal. Normally I like to annotate working code, but in this case the requirements are a little different. The code itself isn’t actually going to change a great deal, but we’re going to be exploring the effects of changing XML asttributes on the layout itself and the child items. To achieve this there is a companion app which has been published to Google Play Store which allows you to control the various attributes. The source code of the app will be published in due course, but in the meantime I courage you to download the app and play along as we go!
It is also worth mentioning that I shall be approaching the explanations in this series very much from an Android perspective – that is, I’ll be using the standard Android layouts as a point of reference and highlighting where FlexboxLayout can give similar results.
To use FlexboxLayout in your project first add a dependency to your build.gradle:
Then it is simply a case of including it in your XML layouts (or programatically, if necessary) – I won’t go in to more detail here as the examples on the Github repo should be more than sufficient.
In very basic terms, FlexboxLayout is closest to LinearLayout because it positions its children sequentially – each child is positioned after the previous one. One thing that we need to do with LinearLayout is set the orientation, and that brings us neatly on to the first attribute of FlexboxLayout that we’re going to look at:
This controls the direction of flow when laying out the children and is, as already suggested, similar to how
orientation works for LinearLayout. The values
column are equivalent to horizontal and vertical orientations respectively. However there are also two other values we can use
column_reverse these do exactly the same thing only they lay the children out in the opposite direction. For example,
row will start at the left and will place each subsequent child to the immediate right of the previous one:
row_reverse will start at the right and place each child to the immediate left of the previous one:
There are a couple of terms which we need to define here as they will be referenced throughout the remaining definitions. The main axis is the direction of flow defined by the
flexDirection and the cross axis is the axis perpendicular to the main access. So for
row_reverse the main axis would the horizontal axis and the cross axis would be the vertical axis. Remember these – you’ll need them later!
The first major difference between FlexboxLayout and LinearLayout is the behaviour when the flowed children reach the bounds of the layout itself. For LinearLayout the children are simply clipped so that once the layout bounds have been exceeded, adding subsequent child Views will simply position them outside of the layout. With FlexboxLayout we can control this behaviour using the
flexWrap attribute. If we set this to
nowrap then when we add children after we have filled the layout along the main axis, they will be added at the end and preceding children will be shrunk to make room. There is some finer-grained control that we can do on this, and we’ll discuss this when we look at child attributes later in the series.
The way that child items are positioned along the main axis is controlled by
justifyContent. At a superficial glance this may appear similar to
flexDirection, until we look at it a little closer.
flexDirection controls the order of the child items whereas
justifyContent controls the relative positioning. The possible values are
alignItems controls the positioning and sizing of items along the cross axis. The possible values are
This is where it can get slightly confusing because
alignContent appears be the same as
alignItems but actually there is a subtle difference which has a major effect on behaviour! Whereas
alignItems controls how items are positioned within their own line,
alignContent controls the line itself. In Android-like terms it’s similar to TableRow within TableLayout: Using
alignContent is similar to applying layout attributes to TableRow; whereas
alignItems is similar to applying layout attributes to the child views representing the individual table cells. The possible values are
The best way to get an understanding of
alignContent really is to play with it. In my app, set
Flex wrap to
Wrap, add some additional cells (by clicking the AppBar “Add” action) until it wraps on to a second row, set alignContent to stretch to enable you to visualise the line dimensions, and then play with different values of alignItems.
So that’s pretty powerful and flexible (yeah, I know!) stuff. But there’s a lot more. In the next article we’ll look at how we can control individual child items as well.
The app is available in the Google Play Store, and the source code for the app will be published at the conclusion of this series.
© 2016, Mark Allison. All rights reserved.
Copyright © 2016 Styling Android. All Rights Reserved.
Information about how to reuse or republish this work may be available at http://blog.stylingandroid.com/license-information.