Percent Support Library – what, when, how?

What, when?

With the release of Android M (API 23) the Support library got a major update as well. One of the unsung heroes is a feature badly requested since Android’s early days – the ability to set dimensions in percentages. With the release of the Percent Support Library is’t now possible to set a View to take exactly 30% of the screen, or to set it’s marginTop to 10% for example.

 

How?

The Percent Support Library adds two new layout managers in the developers’ toolbox – PercentFrameLayout and PercentRelativeLayout. As their names suggest they derive from the well-known FrameLayout and RelativeLayout, with the extension that they support the new PercentLayoutHelper.PercentLayoutParams.

Using percents in your apps is easy:

1. Add a dependency in your build.gradle file

compile 'com.android.support:percent:23.1.0'

2. Add one of the Percent layout managers to your layout

<android.support.percent.PercentRelativeLayout 
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
	
</android.support.percent.PercentRelativeLayout>

3. Within this parent use the new percent attributes

<Button
    android:layout_height="wrap_content"
    android:text="50% width button"
    app:layout_widthPercent="50%"    
    app:layout_marginTopPercent="10%" />

The list of allowed percent attributes is:

  • layout_widthPercent
  • layout_heightPercent
  • layout_marginPercent
  • layout_marginLeftPercent
  • layout_marginTopPercent
  • layout_marginRightPercent
  • layout_marginBottomPercent
  • layout_marginStartPercent
  • layout_marginEndPercent
  • layout_aspectRatio

All of those should be self-explanatory. The first two are substitutes for the standard android:layout_width/height attributes. If you specify one of the new layout_widthPercent/heightPercent, you do NOT need to specify the standard corresponding attribute.

The layout_aspectRatio is interesting. It allows you to specify only one of the width / height and the other dimension will be automatically calculated based on the layout_aspectRatio. Note that the ratio is always width:height. So:

  • for layout_width="100dp" app:layout_aspectRatio="50%" the height will be 200dp
  • for app:layout_aspectRatio="200%", height = 50dp

The following pic illustrates this behavior.
aspect_ratio_example

 

Notes

Note 1: The developer docs say:

If you want the view to be able to take up more space than what percentage value permits, you can add layout_width/height="wrap_content". In that case if the percentage size is too small for the View’s content, it will be resized using wrap_content rule.

This behavior was NOT working correctly with version 23.1.0 for me. Instead what I found out is that there’s strict priority of the attributes that’s followed.

app:layout_heightPercent stronger than android:layout_height stronger than app:layout_aspectRatio.

So if more than one of those is specified for a View, the system will only take into account the strongest of those.

 

Note 2: If you don’t specify any of the standard android:layout_width/heigh, LINT will complain with a warning like the following:
percent_lint_warning
As long as you’ve provided any of the “new” percent required attributes, the code will compile and run perfectly normal, but this warning can break builds configured to abort on lint errors. Unfortunately I couldn’t find a better solution so ended up suppressing the warnings manually when needed.

 

Conclusion

I created this simple GitHub project with more a few more examples. Check out the source if you want to solidify your understanding of the Percent Support Library.

I see this library making our lives easier when creating responsive layouts across variety of screen sizes. Another nice usage will be when dealing with ImageViews, especially when we want them to be of certain dimensions. I’ll be happy if you leave a comment with your ideas of where this support library will be handy.

2 Comments

  1. how can i set a negative margin right percent for an ImageView inside the PercentRelativeLayout ?

    Reply
  2. Unfortunately you can’t set negative percent margins 🙁 You can set negative solid dp margins, but that will most likely break the whole idea of using the Percent library in the first place. Perhaps you can rework your layout so that you don’t need the negative margin?

    Reply

Submit a Comment

Your email address will not be published. Required fields are marked *