Creating responsive “Buttons Bar” widget in Android (part 1)
Tags: android, androidappdev, androiddev
Published: 2019-01-29 06:47:50

---
title: Creating responsive “Buttons Bar” widget in Android (part 1)
published: true
description: 
tags: Android, AndroidAppDev, AndroidDev
---


Today’s web developers have plenty tools to build modern, fast and (most of all) responsive web pages. But when it comes to Android, things are not so bright. We’re tightly bounded to what our native “system” has to offer. And there is not so much of responsivness there ;)

#The Problem

Recently I’ve had to do some custom ui, which will act accordingly to different language translations and changing numbers of elements inside. Believe me, one which looks good in english, can get pretty extended in other languages.

Below, you can find an example ui visualisation:

![](https://thepracticaldev.s3.amazonaws.com/i/m2zyoihtimave0165r8v.png)

Everything looks great! We have slick icons, great labels, tremendeous white spaces…but what if someone would like to use longer names, of more than three buttons? And what about smaller phones screens?

We could use LinearLayout’s weight approach, with some TextView’s autosizing and try to divide elements accordingly, but without knowing theirs initial width, we could end like this:

![](https://thepracticaldev.s3.amazonaws.com/i/eeublctxa3afacxw3xlj.png)

Some will say: “ Success. Everything is distributed evenly. It’s readable. We can end it right know.”

But not us. We want greater control and to have everything unified. Fonts, spaces, icons… you name it. We want this:

![](https://thepracticaldev.s3.amazonaws.com/i/be7j8ndb83e7aaz8jc6m.png)

Much better! Each element has same font size and takes as much space as he wants and can get from its parent.
The aim is to apply strategies to containers view children, untill they reach desirable state, whether by having smaller font, smaller paddings or even icons hidden! Every strategy should apply to each children, so we could get an consistent and more pleasant look.

#The Solution

I assume you know how to create new project, so I will skip this unrelevant part ;)
What I want to do, is to prepare a compound view (ButtonBarViewHolder), which will act as a container for particular view items (ButtonBarItem). So, my ButtonBarViewHolder could implement it’s own way of dealing with measuring and placing its children. I think, to achieve best results I shouldn’t just limit myself to applying only one method for optimising child items, but I will talk about it later (how it could be used as a responsive bottom bar widget).

Let’s start with preparing some building blocks.

{% gist https://gist.github.com/krzysztofbalana/bd36e04c213db46a108adc92be9bc7ff %}

attr.xml

{% gist https://gist.github.com/krzysztofbalana/05f38c1c36525efbbfbc126ac585d761 %}

ButtonBartemsHolder.kt

{% gist https://gist.github.com/krzysztofbalana/caa9469eb44d1e11e4301d509cceb82f %}

We will use it more in just a moment.

view_button_bar_item.xml

{% gist https://gist.github.com/krzysztofbalana/e123ff7d2680d9748f456c7c064fdf36 %}

activity_main.xml

{% gist https://gist.github.com/krzysztofbalana/7b0ba8f6e7ec5997fffefb6d12f3eeba %}

Ok! Having all what is needed to present problem, we can now start and measure desired width and after that, children’s width’s in order to determine if they cumulative size exceeds our desired width (or not).

In order to achieve a proper and measured childrens, we will need to use a recursion during viewholder’s onMeasure() pass. It makes widget computational heavier, due too more than two measuring passes (normally from 4 to 5, and sometimes more). Be careful! Using this approach in many places on one screen can lead to frame drops or stackoverflow.

ButtonBarItemsHolder:

{% gist https://gist.github.com/krzysztofbalana/b22818e66683c08300aa972607db55a5 %}

*As you can see, we’ve measured deisred (parent) width and having that knoweledge asked its children to measure themself . Next we will match measured childrens againts parent and try to use a strategy, which will execute some kind of “tweaks” to childrens.*

For this we’ll use an interface:

{% gist https://gist.github.com/krzysztofbalana/8d9c704bf44c9f97c169df932d0c882d %}

and concrete implemetation:

{% gist https://gist.github.com/krzysztofbalana/7520a9a3520b506776b9364608f474cf %}

This strategy will try to downsize fonts of given view and call “onDepleted” when reach end (which in this case is minimum font sie of 10 points).

We could this strategy it in ButtonBarItemsHolder directly, but (in my opinion) it will be better to delegate it to other class. We could use some kind of strategies executor, which will execute all the strategies we will provide to it.

{% gist https://gist.github.com/krzysztofbalana/fc29eb65b520c89ce21b3aec7da94af2 %}

Having working executor, we can now add it to our ButtonBarItemsHolder and launch inside recalculateChildren() methods body.

{% gist https://gist.github.com/krzysztofbalana/d8bc8d262ebf12c971e460a223803e4b %}

Uff! Finally made it trough part 1 of our mini series! Now our “widget” is a little more responsive than it was before. In further steps we will try to add more strategies (like changing paddins, hiding icons etc) and position.

![](https://thepracticaldev.s3.amazonaws.com/i/r85uj43iqakl4ny92zha.png)


You can always check working example on my github if you like.

https://github.com/krzysztofbalana/buttons-bar-navigation