Recreating Apple’s Rubber Band Effect in Swift

For the past 6 months we have been working on the most challenging and fun app I have ever developed: Thoughts. This is also the first Produkt’s own app, so we couldn’t be more excited about its imminent launch.

One of the trickiest features we encountered while developing Thoughts was to recreate Apple’s scrolling view capabilities (some of them).

Whilst Panning and Zooming can be defined by using gesture recognizers, combining the two was far more complicated. Zooming into a specific point (e.g. middle of your fingers) involves not only zooming but shifting the content. Nevertheless, my favourite part of all was to replicate the rubber band behaviour.

Thoughts zooming — brief video showing Thoughts enormous zooming and rubber band behaviour

The maths behind it

The Control Centre is a perfect rubber band interaction example.

Control Center adds rubber band behaviour when it is pulled up

By interacting with the Control Centre behaviour, the first mathematical function that came to my mind was the square root. However… it didn’t feel right, and not as natural as Apple’s. Here is when Swift (and specially playgrounds) became very useful.

Swift playground for finding the most appropiate mathematical function

After a few tests, the best strategy was to use log10 — it mimics quite closely Apple’s built-in behaviour.

Logarithmic functions (screenshot from Tydling app)

I tried multiple logarithmic functions, including the neperian, but log10 was the most optimal.

The GIF below illustrates the comparison between square root, log10 and a function involving a power of 4. This last function works very well and, depending on the exponent, the ‘rubber’ effect becomes more/less elastic (that is, the distance gets longer/shorter). However, the downside of using this function is that there is a maximum value you shouldn’t cross (otherwise, the movement gets reversed).

Using this behaviour in ‘real life’ interactions

Replicating Apple’s scroll view will not be necessary on a standard app; we did it for Thoughts to create its infinite canvas. However, some situations (like the example below) can require a rubber band effect where there is no scroll view involved.

To showcase one of the above functions, I have included the following example in the project.

The green view is located using Autolayout and has a PanGestureRecognizer attached to it that calls the following method:

Where the last part of it, the logConstraintValueForYPoisition, takes care of applying the rubber band effect after the view exceeds the vertical limit using a log10 function. Tip: I like to use log10 from 1 to X (0.x values grow massively quick).

In this example, animateViewBackToLimit() is implemented using a simple UIView animation block to keep the project simple, however I am not a big fan of them.

Find the project in GitHub

One last word

UIAttachmentBehaviour can also be used in some situations involving rubber band behaviour. This is only another tool to add in your toolbox ☺

PS: this is the first time I have published Swift code. I would really appreciate if you can help me to improve it in any way.