Solving wrapping issue with FlexboxLayout in Android

By xngo on February 24, 2019

Overview

While developing my Android app, iTransit, a time schedule application for bus and metro, it hits a wrapping issue. The application has to display a list of bus numbers for the users to choose. The problem is, there are more than 400 bus numbers in Montreal. Currently, TableLayout is being used but it has a limitation. You have to predefine the number of columns. When users change from portrait mode to landscape mode, there is a big empty blank space on the right side. That is bad! Obviously, you can solve this by calculating yourself how much columns you can put in the portrait mode and in landscape mode. Then, switch accordingly. This is getting complicated and I don't want to do all these hard work.

Why do the heavy lifting, when there is FlexboxLayout, an external library made by Google. It is designed specifically to handle wrapping. Now, let's use it.

Include FlexboxLayout library

In app/build.gradle, add the following dependency:

dependencies {
    implementation 'com.google.android:flexbox:1.0.0'
}

Define FlexboxLayout

In res/layout/activity_main.xml, add the following:

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:scrollbars="vertical">
 
    <com.google.android.flexbox.FlexboxLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:id="@+id/flexbox_view"
 
        app:flexWrap="wrap"
        app:justifyContent="space_evenly"        
        />
 
</ScrollView>

Note: It is important to add app:flexWrap="wrap" attribute. Otherwise, wrapping is not going to be activated.

The code

There is no special coding to be done with FlexboxLayout. You treat it the same way as the other layouts. In your MainActivity class, simply add your views to the FlexboxLayout. That's it.

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.TypedValue;
import android.widget.Button;
 
import com.google.android.flexbox.FlexboxLayout;
 
public class MainActivity extends AppCompatActivity {
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
 
        FlexboxLayout flexboxLayout = this.findViewById(R.id.flexbox_view);
 
 
        // Add a lot of buttons.
        for(int i=0; i<70; i++) {
            Button button = new Button(this);
            int btnHeight = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 40,
                                                        this.getResources().getDisplayMetrics());
            int btnWidth = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, 70,
                                                        this.getResources().getDisplayMetrics());
            button.setWidth(btnWidth);
            button.setHeight(btnHeight);
            button.setText(String.valueOf(i));
 
            flexboxLayout.addView(button);
        }
    }
}

The end results

FlexboxLayout output portrait mode FlexboxLayout output landscape mode

Github

  • https://github.com/xuanngo2001/android-flexbox-wrap

Reference

  • https://github.com/google/flexbox-layout

About the author

Xuan Ngo is the founder of OpenWritings.net. He currently lives in Montreal, Canada. He loves to write about programming and open source subjects.