Written by Adrian Kremski
Android Developer
Published March 25, 2016

Working with the Percent Support Library

Google released new Percent Support Library which contains two extra container classes: PercentFrameLayout and PercentRelativeLayout. I want to show you how to work with these layouts which are great in handling percentage-based sizing of widgets.

Most of the Android developers need only general containers available in core software development kit – FrameLayout, LinearLayout, RelativeLayout, TableLayout and GridLayout. These layouts work as expected, however they have some limitations: they are not good in handling percentage-based sizing of widgets inside of them. To fill this gap, Google has released the Percent Support Library with PercentFrameLayout and PercentRelativeLayout.

PercentFrameLayout and PercentRelativeLayout

PercentFrameLayout and PercentRelativeLayout are descendant classes from FrameLayout and RelativeLayout. Apart from the ancestor’s features, new implementations give us extra layout attributes that will help with setting percentage-based widget sizes. There attributes are as follows:

  • app:layout_heightPercent
  • app:layout_widthPercent
  • app:layout_marginLeftPercent
  • app:layout_marginTopPercent
  • app:layout_marginBottomPercent
  • app:layout_marginRightPercent

Let’s see them in action!

Using Percent Support

To test our new library, we will try to prepare simple screen with 3 boxes aligned diagonally.
Screen Shot 2016-03-23 at 20.37.14

LinearLayout

Before choosing percent library we will try to achieve desired effect with the LinearLayout.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.055" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.26"
            android:orientation="horizontal">

            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.055" />

            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.26"
                android:background="@color/colorPrimary"
                android:gravity="center"
                android:text="#1"
                android:textColor="@android:color/white"
                android:textSize="20sp" />

            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.685" />

        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.055" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.26"
            android:orientation="horizontal">

            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.37" />

            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.26"
                android:background="@color/colorPrimary"
                android:gravity="center"
                android:text="#2"
                android:textColor="@android:color/white"
                android:textSize="20sp" />

            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.37" />
        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.055" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.26"
            android:orientation="horizontal">

            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.685" />

            <TextView
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.26"
                android:background="@color/colorPrimary"
                android:gravity="center"
                android:text="#3"
                android:textColor="@android:color/white"
                android:textSize="20sp" />

            <View
                android:layout_width="0dp"
                android:layout_height="match_parent"
                android:layout_weight="0.055" />

        </LinearLayout>

        <View
            android:layout_width="match_parent"
            android:layout_height="0dp"
            android:layout_weight="0.055" />

    </LinearLayout>

Result:
Screen Shot 2016-03-23 at 20.04.01

As you can see, the above xml gives us what we wanted but the implementation is far from perfect (a lot of boilerplate code + extra Views used as padding). So let’s try harder.

PercentFrameLayout

For the second option we are going to use PercentFrameLayout, but first we need to add the library to our gradle build.

dependencies {
    compile 'com.android.support:support-v13:23.1.1'
    compile 'com.android.support:percent:23.1.1'
}
android {
    compileSdkVersion 23
    buildToolsVersion "23.0.2"
    defaultConfig {
        minSdkVersion 17
        targetSdkVersion 18
    }
}

Now that our percent support is added, let’s implement the screen.

    <android.support.percent.PercentFrameLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!--suppress AndroidDomInspection -->
        <TextView
            android:background="@color/colorPrimary"
            android:gravity="center"
            android:text="#1"
            android:textColor="@android:color/white"
            android:textSize="20sp"
            app:layout_heightPercent="26%"
            app:layout_marginLeftPercent="5.5%"
            app:layout_marginTopPercent="5.5%"
            app:layout_widthPercent="26%" />
        <!--suppress AndroidDomInspection -->
        <TextView
            android:background="@color/colorPrimary"
            android:gravity="center"
            android:text="#2"
            android:textColor="@android:color/white"
            android:textSize="20sp"
            app:layout_heightPercent="26%"
            app:layout_marginLeftPercent="37%"
            app:layout_marginTopPercent="37%"
            app:layout_widthPercent="26%" />
        <!--suppress AndroidDomInspection -->
         <TextView
            android:background="@color/colorPrimary"
            android:gravity="center"
            android:text="#3"
            android:textColor="@android:color/white"
            android:textSize="20sp"
            app:layout_heightPercent="26%"
            app:layout_marginLeftPercent="68.5%"
            app:layout_marginTopPercent="68.5%"
            app:layout_widthPercent="26%" />
    </android.support.percent.PercentFrameLayout>

With PercentFrameLayout our “padding Views” were replaced with app:marginLeft/TopPercent attributes and android:layout_weight with layout_widthPercent.

Result:
Screen Shot 2016-03-23 at 20.50.04

There is one thing we could still do better which is expressing our margins. Right now they are not relative to the preceding box. However we can change that by using PercentRelativeLayout.

PercentRelativeLayout

    <android.support.percent.PercentRelativeLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent">
        <!--suppress AndroidDomInspection -->
        <TextView
            android:id="@+id/first_square"
            android:background="@color/colorPrimary"
            android:gravity="center"
            android:text="#1"
            android:textColor="@android:color/white"
            android:textSize="20sp"
            app:layout_heightPercent="26%"
            app:layout_marginLeftPercent="5.5%"
            app:layout_marginTopPercent="5.5%"
            app:layout_widthPercent="26%" />
        <!--suppress AndroidDomInspection -->
        <TextView
            android:id="@+id/second_square"
            android:layout_below="@id/first_square"
            android:layout_toRightOf="@id/first_square"
            android:background="@color/colorPrimary"
            android:gravity="center"
            android:text="#2"
            android:textColor="@android:color/white"
            android:textSize="20sp"
            app:layout_heightPercent="26%"
            app:layout_marginLeftPercent="5.5%"
            app:layout_marginTopPercent="5.5%"
            app:layout_widthPercent="26%" />
        <!--suppress AndroidDomInspection -->
        <TextView
            android:id="@+id/third_square"
            android:layout_below="@id/second_square"
            android:layout_toRightOf="@id/second_square"
            android:background="@color/colorPrimary"
            android:gravity="center"
            android:text="#3"
            android:textColor="@android:color/white"
            android:textSize="20sp"
            app:layout_heightPercent="26%"
            app:layout_marginLeftPercent="5.5%"
            app:layout_marginTopPercent="5.5%"
            app:layout_widthPercent="26%" />
    </android.support.percent.PercentRelativeLayout>

As you can see the margins used in our last example are not based on the distance from the left edge but they are relative to the preceding views.

If you want to check full use cases, visit my Github repo and build it by yourself.

usecase

Thanks for reading !

Written by Adrian Kremski
Android Developer
Published March 25, 2016