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.
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>
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.
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.
Thanks for reading !