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.
The maths behind it
The Control Centre is a perfect rubber band interaction example.
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.
After a few tests, the best strategy was to use log10 — it mimics quite closely Apple’s built-in behaviour.
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.
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.