HomeNewsFrom design to android, part 2 – Saul – Medium

From design to android, part 2 – Saul – Medium

medium bookmark / Raindrop.io |

It’s been a long time since my previous post, many things have happened since then, but finally is here. I hope you enjoy it!.

This is a new story in my series of articles called ‘From design to android’, if you remember the first part of these series, I pick a design concept which I find interesting and I try to implement it on Android, focusing on some interesting topics along the the way from my android developer perspective.

All the code referred in this post can be found at this Github’s repository👈

This is the concept that I’ve chosen for this part:

1*-2PD1PyuxLrB9mjoVzP2rQ.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*-2PD1PyuxLrB9mjoVzP2rQ.gif”>

Google business — Slider by Johny Vino

I used once again a concept coming from Johny Vino.

Try to stop for a second figuring out, as an android developer as you are, how to make an implementation of that screen.

If you spotted two of the following points you maybe agreed with me, at first sight, there were two parts that came to my mind:

  • How to implement the animation of the building, of course.
  • That seekbar could not be as trivial as it should be

Animating the building

Let’s put this exercise on a perfect environment, we may ask our designer(s) to create the animation. After maybe, some After Effects work + the Bodymovin’s plugin, they could give us the desired animated vector drawable.

Or…, we might have no designer at all, and you are a brave and lonely developer which needs to have this done without much design skills, let’s try that path.

Working with vectors

With some minor work on a vector based tool like Sketch or BoxySvg we could easily vectorise the building image. Grouping those parts whose will be animated into groups will be useful for a next point.

1*sK6g7Il9jVSnyode1nsjqw.png<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*sK6g7Il9jVSnyode1nsjqw.png”>

Creating the desired image on Sketch

Next, a new amazing tool comes to the scene, and this one is Shape Shifter, from Alex Lockwood. This awesome tool helps you to animate SVG based images and exporting those animations into an AVD among other formats.

1*6vPUlrUQ1Q4IiqwIt9_o-Q.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*6vPUlrUQ1Q4IiqwIt9_o-Q.gif”>

Shape Shifter

After creating the desired effect in a few clicks, we can export our fresh animated vector drawable, paste it into Android Studio, bind it to an ImageView and we are done!.

(img_building.drawable as Animatable).start()
1*DgQkbwVvYhZyH0Y2A8SzlA.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*DgQkbwVvYhZyH0Y2A8SzlA.gif”>

Exported ShapeFilter’s avd running on an android device

Yeah, amazing, right?! We just built a great animation effortlessly, but, if we look again at Johny Vino’s concept, we’ve missed minor detail. The animation is handled by a slide bar, (known as Seekbar on Android) which handles the sate of the animation depending the progress of the bar.

So what we need is so far to set the progress of the animation within an AVD. Well… that’s not currently supported from what I’ve seen, (Lottie does). We just have at our disposal methods like, .start().stop() and reset().

At this point we could try the following:

1*aAbK06sdpSU9VSj039PgUg.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*aAbK06sdpSU9VSj039PgUg.gif”>

Or keep going, let’s iterate just a bit more.

Animated Selector Drawables

In our current point we have an animation which needs to be commanded to go to an specific frame when the SeekBar reachs an specific position. In other words we have some states during the animation.

Let’s declare some attributes for defining these frames or states.

<declare-styleable name="BuildingState">
<!-- Idle state -->
<attr name="state_zero" format="boolean"/>
<!-- One flat and a simple roof -->
<attr name="state_one" format="boolean"/>
<!-- Two flats and expanded roof -->
<attr name="state_two" format="boolean"/>

In this point let me introduce a maybe not well known drawable, the AnimatedStateListDrawablewhich totally will save our day.

Let’s refer to the android documentation:

Drawable containing a set of Drawable keyframes where the currently displayed keyframe is chosen based on the current state set. Animations between keyframes may optionally be defined using transition elements.

This drawable can be defined in an XML file with the <animated-selector> element. Each keyframe Drawable is defined in a nested <item> element. Transitions are defined in a nested <transition> element.

Looks somewhat what we are looking for, right? We could define some <items> which will identify the different frames in our animation, and transitions for how transition an item to another.

Since every <item> tag would represent our frame, we’ll define three of them, each of one composed by a vector drawable.

1*f3eIyZbq766fa_D6AKenYw.png<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*f3eIyZbq766fa_D6AKenYw.png”>

And each<transition> will represent how an <item> transitions to another, we’ll need 4 for transitioning through all the frames back and forth.

With the aforementioned Shape Shifter, we can easily export the required AVDs into Android Studio, which will work as transitions in the AnimationStateListDrawable.

1*fcjhx9sPrA0CZjBsA5H1FA.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*fcjhx9sPrA0CZjBsA5H1FA.gif”>


1*SQm2c0dOGTj_hXqR6djESQ.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*SQm2c0dOGTj_hXqR6djESQ.gif”>


And finally the whole AnimatedStateDrawable we just built:

<?xml version="1.0" encoding="utf-8"?>









Tweaking a bit our activity and our layout we set this amazing AnimatedSelectorDrawable into an ImageView as the source resource, and making use of the setImageStatemethod with the desired state, the animation will work magically as expected.

private val STATE_ZERO = intArrayOf(
R.attr.state_zero, -R.attr.state_one, -R.attr.state_two

private val STATE_ONE = intArrayOf(
-R.attr.state_zero, R.attr.state_one, -R.attr.state_two

private val STATE_TWO = intArrayOf(
-R.attr.state_zero, -R.attr.state_one, R.attr.state_two
private fun onSeekProgressChanged(position: Int) {
val max = seekbar.max

val businessType = when(position) {
in 0..max/3 -> STATE_ZERO
10..max/2 -> STATE_ONE
20..max/1 -> STATE_TWO
-> throw IllegalStateException()

imageView.setImageState(businessType, true)


1*A79i7YzBIlJCtzZVlON5KQ.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*A79i7YzBIlJCtzZVlON5KQ.gif”>

Animating Seekbar’s thumb

Yai! So far, we’ve reached one of my two hot points, the second one is manage how to animate the Seekbar thumb’s size during the progress, as Johny Vino does in his concept:

1*P-q4HkBVBMT_KtL3yfFqNw.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*P-q4HkBVBMT_KtL3yfFqNw.gif”>

Size of the Seekbar’s thumb on dragging

We can distinguish two behaviours here:

  • The thumb size its being increased in some way related with the progress
  • When releasing, some kind overshooting animation its being performed

A visit to the ScaleDrawable

Other unknown drawable (at least for me) is the ScaleDrawable, let’s refer again the android documentation:

A Drawable that changes the size of another Drawable based on its current level value. You can control how much the child Drawable changes in width and height based on the level, as well as a gravity to control where it is placed in its overall container. Most often used to implement things like progress bars.

The default level may be specified from XML using the android:level property. When this property is not specified, the default level is 0, which corresponds to zero height and/or width depending on the values specified for android.R.styleable#ScaleDrawable_scaleWidth scaleWidthand android.R.styleable#ScaleDrawable_scaleHeight scaleHeight. At run time, the level may be set via setLevel(int).

So, it seems that we could define some kind of drawable which will refers another drawable, a level, and a scale factor. If we attach the progress of the bar to that level, it should work, right?.

Let’s define a layer list of drawables and, since we only want the blue part to be scaled, we’ll wrap it into an ScaleDrawable.

<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:tools="http://schemas.android.com/tools"

<aapt:attr name="android:drawable">
<shape android:shape="oval">

<solid android:color="@color/blue_accent_200" />
<shape android:shape="oval">
<solid android:color="#FFF" />

As you may see, using the <aapt> tool we can inline required attributes right in the <layer-list>

1*RJ5CGWWAptO1QMVp9iGpUw.png<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*RJ5CGWWAptO1QMVp9iGpUw.png”>

thumb <layer-list> containing a ScaleDrawable

Now we just only have to tweak again our activity to set the level of the ScaleDrawable, right when the progress of the SeekBar changes, notice also what nice is it that we can use the level property from the Drawable of the thumb.

private fun onSeekProgressChanged(position: Int) {
// ...

((seekbar.thumb as LayerDrawable)).level =
(position * (SCALE_MAX / seekbar.max))

And the result:

1*sCaG8_x3C9zcW2v-j2pTBQ.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*sCaG8_x3C9zcW2v-j2pTBQ.gif”>

Now we just have to animate the thumb when releasing, we can get rid of that making use of the ScaleDrawable and a ValueAnimator.

private fun animateThumbRelease() {
val thumb = seekbar.thumb
val initLevel = thumb.level
val maxLevel = thumb.level * THUMB_RELEASE_SCALE_FACTOR
val animator = ValueAnimator.ofInt(
initLevel, maxLevel, initLevel)

with(animator) {
interpolator = OVERSHOOT

addUpdateListener {
thumb.level = it.animatedValue as Int



1*rA76TXFkXAeslnspZOUEkA.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*rA76TXFkXAeslnspZOUEkA.gif”>

Wrapping up

At this point we’ve solved the issue with the animation, and after that the one with the Seekbar, with a few more trivial modifications as creating an AVD for the moving clouds, using the new font as resources capability for our texts, and adding a fresh new adaptive icon, we have something quite similar to the Johny Vino’s concept.

I hope you enjoyed during the road and, if you have to kill me because something, please do it with a nice comment and an aggressive emoji.

Final result:

1*WfNBTsNo_9ipck02sUoU_w.gif<img class=”progressiveMedia-noscript js-progressiveMedia-inner” src=”https://cdn-images-1.medium.com/max/1600/1*WfNBTsNo_9ipck02sUoU_w.gif”>

Github Repository

here 👈


Featured articles on Prototypr: