Animations challenges #1 — Bear iOS Search animation

Aymen Rebouh
Jan 18 · 6 min read

Animations challenges is actually pretty fun. It’s about picking a random animation in one of the app that we use everyday ( twitter, Facebook, Slack, others .. ) and try to recreate it together by doing Pair Programming.

December 12 was the first day for me or John, both iOS Engineer at Eureka, for our Animations Challenges.

Animations are very funny. When you look at them, they look very simple, but when you try to look closer, you will notice that it involves many changes/sub-animations under the hood, making the end result amazing and almost unnoticed.

So the goal of those animations challenges is to try to analyse those animations and try to replicate them. After that, there will be a blog article showing how we approached this challenge.

Before diving into our first challenge, I would like to explain how we proceeed.

Process and conditions

Duration =~1h
Process: Pair programming and Pomodoro Technique

The Pomodoro Technique is about using a timer to break down work into interval. We try to switch every 15 minutes and allow each other to work on it.

It has great advantages, such as allowing both of us making technical decisions while the observer is asking questions making sure we are doing things right.

Introduction

The first animation we decided to reproduce within one hour was the search animation from the Bear iOS app.

Let’s dive in

Observation #1 — Three different states

First, we observed that it involves three different states:

  • The search is empty = start or default state
  • The search button is full = full state
  • The search button is scaled = final state

Let’s create a SearchView with properties that represents those three different states:

PS: We want the progress of the animation to be between 0 and 1.

Observation #2 — Scroll down to reach the goal

Animations happens when we scroll from top to bottom, which means that we have to:

  • Decide when the goal (final state) is reached. For exemple, after scrolling about 50 points vertically, it may means that we finished
  • Scrolling from top to bottom will generate a negative offset, so since we want to play with positive values, we cast it to a positive value
  • Since we are playing with a progress property, we want it to be between 0 and 1 ( 0% a and 100% )

And let’s add an empty search function for now

Observation #3 — Two search buttons?

When looking at it closer, we see that while scrolling, we can see two different stroke colors at the same time for the search icon.

So based on that, we supposed that:

  • There are maybe two buttons with the same size but different background and stroke color. The foreground button has a yellow dark background color with white stroke while the background button has a clear background color with a gray stroke
  • There is a mask (which can be a CAShapeLayer ) that hide/show a part of the foreground button.
  • As the user scroll, we are going to play with the mask path to show and hide the foreground button depending on the progress of the animation

So let’s fill our SearchView class now!

And then let’s layout everything:

Finally, let’s call the setup method when the view is initialized:

Observation #4 — Time to start filling

On the Observation #2, we created an empty update function.
This function will take care of making this animation possible, and the first step is to start reproducing that “fill” animation

There is a mask (which can be a CAShapeLayer ) that hide/show a part of the foreground button.

The role of this mask layer is to show/hide the foreground button (the one with the yellow dark background color), based on the mask path, that’s how we can create this “fill” animation.

If the mask layer path is nil ( default value ), the view it’s associated with ( foreground button ) will not be visible. This is the case right now.

So let’s try to change this mask layer path properties based on the progress of the scroll and see what’s happening:

Wow! It start looking like something already! Let’s just tweak a little bit the starting point of this so that the animation start from the bottom to the top as we want, instead of the opposite.

We are almost there! Now we have to take care of the scaling!

Observation #5 — Scaling to finish

Now that we can reach the full state, we need to make it to the final state when it’s scaled.

Let’s define how big we want the button to grow/scale, where 1.0 is the original size.

But there is one thing..Our update function is already using the progress property to change the mask’s path and fill the button completely when the progress is equal to 1.

But if we look at our animation states, the full state should be reached at 0.7, not 1.0. And from 0.7 to 1.0, it should play the scale animation..

So we have to tweak a little the progress property by shifting it from the interval 0…1 to 0…7.

How can we move from a range of 0…1 to 0…7 ?

Let’s apply some math:

  • (progress-newStartInterval) / (newEndInterval — newStartInterval)
  • (progress-0)/(0.7–0)

The new update function become:

Last and final step is to add the scaling feature. And there is another range shifting going on: we want to shift the progress from 0…1 to 0.7…1

Let’s apply some math again:

  • (progress-newStartInterval) / (newEndInterval — newStartInterval)
  • (progress-0.7)/(1–0.7)

So let’s add at the end of the update function the new shifted progress used for scaling the button:

So on the code below, if the progress is bigger than 0.7, then we start scaling based on the new shifted progress, otherwise, we remove the scaling effect;

Final Result

Oh! And if you wanna have the rounded animation like the original animation, then you can make your button a circle:

✅ Good job for reading and reaching the end 💪

You can now reproduce a “similar” animation as the Bear iOS search application

You learned that sometimes, something that looks like a challenge, once putting enough through on it, can be achieved without struggling too much.

This is the first animation challenge blog article I write, and there is going to be more! So if you have any feedbacks, let me know :).

You can find the full animation project there:

If any questions, you can reach me or John on twitter anytime :).


Eureka Engineering

Learn about Eureka’s engineering efforts, product developments and more.

Aymen Rebouh

Written by

Like learning. You can find me at twitter.com/aymenworks or github.com/aymenworks

Eureka Engineering

Learn about Eureka’s engineering efforts, product developments and more.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade