Dynamic Selectable Pills on Android

Sumeet Devidan
helpshift-engineering
3 min readJul 5, 2020
Adjusting in available space

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.

Pill 9 patch png

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:

  1. Get device metrics, figure out how much width we can occupy, taking into consideration the scale factor provided.
  2. Maintain a list of LinearLayout layouts. This list will hold all the LinearLayouts we create programmatically.
  3. Start a loop to inflate pills layouts and measure the elements that we will add programmatically.
  4. Make a LinearLayout oriented horizontally horizontalLayout. This will be used to add pills one by one until we occupy the maximum space allowed.
  5. Inflate pill layout for each item and set title string in the text view.
  6. Add this layout to the horizontalLayout we created above.
  7. Measure horizontalLayout after each addition of pill. Measure gives us a good idea for how much this element is going to occupy on screen.
  8. If measure exceeds the max available width, then remove the last item added and add horizontalLayout to layouts .
  9. Continue the loop until all items are accounted for.
  10. Add layouts to containerView .

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.

--

--