SwiftUI: A Better Way To Support “Reduced Motion”

coderExMachina
3 min readFeb 12, 2022

Situation

If you want to truly master accessibility, you have to account for quite a list of different factors, like: High contrast, large font sizes, screen reader support and many more.

Luckily, Apple puts great emphasis on the accessibility of their software. If you have some experience with SwiftUI, you will likely have noticed that there is a huge amount of modifiers that make your apps accessible.

Also, there are countless great articles out there that will give you a good overview of the available SwiftUI APIs and how to use them. Some of the ones that I enjoyed reading most can be found here, here, and here. And there are many more.

Complication

However, there is one specific use case that is currently not implemented in a very convenient way: Accounting for users that requested to “reduce” motion when working with animations.

This becomes apparent, when either using the withAnimation() method to change a value or applying .animation() to create a smooth transition of your UI elements from one state to another. In both cases, SwiftUI does not automatically suppress animations for users that enabled the reduced motion setting on their device — after all, the animation might not trigger much motion and might be required for a good user experience.

Typically, what you would do to account for reduced motion, is to check a view’s environment for the users accessibility preference like this: @Environment(\.accessibilityReduceMotion). Then you would have to use a condition whenever you implement an animation tht should not be performed when “reduce motion” is active. It could look like in the image below.

How we used to do it 🙅🏻‍♂️

Since the environment has to be checked for every view where an animation is applied, this can become somewhat repetitive and you might just forget to do it at some point — but there is a better way!

Solution

So, let’s fix this inconvenience with just a few lines of code. Our goal is to replicate the the original methods but include the check for the users accessibility preference so that we can skip checking the environment and don’t have to use if statements or ternary operators. Have a look below.

How we are supposed to do it 😎

Now we have full control while maintaining a clean code basis: If we want to “force” an animation independent of the user’s accessibility preferences, we use withAnimation() or .animation(), and if we want the animation to only occur if the user did not request to reduce motion we will us withConditionalAnimation() or .conditionalAnimation(). Its as easy as that!

--

--

coderExMachina

I'm an indie developer with a passion for a great UX ✌️