Dynamic Selectable Pills on Android
With server-driven content, there is a need to render content dynamically. Static or pre-defined layouts just act as a placeholder but do not help for achieving adaptable UI/UX.
A small part of dynamically inflating layouts is to adapt to user’s device specs for adjusting the content gracefully in the available space on screen. The attempt is to not make user look out for available options when we can adapt our data into available space.
In this article, we are going to see how to render an array of variable length clickable pills adapting to device specs.
First, let us see what we are going to make:
- Clickable pills with variable length text as dictated by our server.
- Adjusting the pills on UI based on available screen width.
- Moving the overflowing pills in vertically available space to keep content scrollable.
- Adapting to screen width based on device orientation
Observe the pill titled “Green”, which adjusts below or on the same line depending on width available for the component to expand.
The Pill
The pill is a drawable 9 patch PNG image. It is just a hollow/transparent outline image.
This PNG will be used as a background to our dynamic text content.
Text Content
The backend dictates the text content. It can be any length text. We will be generating pills at runtime and adjusting them based on available screen width.
Per Pill layout
We will need a container layout to hold per pill item. This layout will contain the text and the background as the pill PNG drawable. We will essentially inflate this pill multiple times depending on the number of items we want to display.
Adjusting with the available width
The core requirement here is to adjust all the pills on the visible screen with graceful UX. The user wouldn’t need a carousel to scroll through.
We will need certain elements in-hand to work this:
- Context to get device metrics.
- Max available screen width scale factor to indicate what percentage of screen width we can expand into. Ex. 80% of screen width.
- A container layout
containerView
to inflate all our items into. - Per pill item layout to inflate.
- Text view Id in the per pill layout to fill in the text.
- List of titles for the pills as given by our server.
- A click listener for pills.
Algorithm to adjust pills based on available width:
- Get device metrics, figure out how much width we can occupy, taking into consideration the scale factor provided.
- Maintain a list of LinearLayout
layouts
. This list will hold all the LinearLayouts we create programmatically. - Start a loop to inflate pills layouts and measure the elements that we will add programmatically.
- Make a LinearLayout oriented horizontally
horizontalLayout
. This will be used to add pills one by one until we occupy the maximum space allowed. - Inflate pill layout for each item and set title string in the text view.
- Add this layout to the
horizontalLayout
we created above. - Measure
horizontalLayout
after each addition of pill. Measure gives us a good idea for how much this element is going to occupy on screen. - If measure exceeds the max available width, then remove the last item added and add
horizontalLayout
tolayouts
. - Continue the loop until all items are accounted for.
- Add
layouts
tocontainerView
.
This process will adjust horizontal addition of pills till we reach the max available width, create a new horizontal layout for remaining items until all items are added and finally add the whole programmatically created layout to a container that we specify.
The key here is to measure
the layout for how much space the items will occupy.
And that's it!
We have an adjustable layout that can render server-driven data and adapt gracefully to the available screen size.