Mastering the iPhone Silent Mode Animation in SwiftUI

Rohit Saini
5 min readJul 9, 2023

Silent mode is a familiar feature on iPhones that allows users to quickly silence their devices. In this article, we’ll explore how to create a captivating animation that mimics the iPhone silent mode toggle using SwiftUI. We’ll break down each component of the animation, providing the necessary code snippets along the way.

Silent Mode On/Off

Prerequisites

To follow along with this tutorial, you should have a basic understanding of SwiftUI and Swift programming. Knowledge of SwiftUI views, animations, and state management will be beneficial.

Getting Started

Let’s begin by examining the provided Swift code:

import SwiftUI

struct SilentModeView: View {
@State private var onOff: Bool = false
@State private var offOn: Bool = false
@State private var bellColor: Bool = false
@State private var bellRotate: Bool = false
@State private var hideSlash: Bool = false
@State private var hideFromScreen: Bool = false

var body: some View {
ZStack {
// Bell View
Rectangle()
.foregroundColor(.white)
.frame(width: 220, height: 60)
.cornerRadius(30)
// Silent and On/Off Stack
VStack {
HStack(spacing: 20) {
ZStack {
// Bell Icon
Image(systemName: "bell.fill")
.font(.largeTitle)
.foregroundColor(bellColor ? .gray : .red)
.rotationEffect(.degrees(bellRotate ? 0 : -25), anchor: .top)
.onAppear() {
withAnimation(.easeInOut(duration: 0.5).delay(2.3)) {
bellColor.toggle()
}

withAnimation(.interpolatingSpring(stiffness: 350, damping: 3).delay(2.3)) {
bellRotate.toggle()
}
}

// Slash
Rectangle()
.frame(width: 5, height: 40)
.foregroundColor(.gray)
.scaleEffect(x: 1, y: hideSlash ? 0 : 1, anchor: .topLeading)
.rotationEffect(.degrees(-40))
.onAppear() {
withAnimation(.easeOut(duration: 0.8).delay(2.1)) {
hideSlash.toggle()
}
}
}
// On/Off View
VStack {
Text("Silent Mode")
.foregroundColor(.black)
.opacity(0.6)
.fontWeight(.bold)
ZStack {
Text("Off")
.foregroundColor(.gray)
.fontWeight(.bold)
.opacity(onOff ? 1 : 0)
.onAppear() {
withAnimation(.easeOut(duration: 1.2).delay(2.1)) {
onOff.toggle()
}
}
Text("On")
.foregroundColor(.red)
.fontWeight(.bold)
.opacity(offOn ? 0 : 1)
.onAppear() {
withAnimation(.easeOut(duration: 1.2).delay(2.1)) {
offOn.toggle()
}
}
}
}
}
}
}
.offset(y: hideFromScreen ? -UIScreen.main.bounds.height / 2.4 : -UIScreen.main.bounds.height / 1.8)
.onAppear() {
withAnimation(.easeInOut(duration: 0.5).delay(2)) {
hideFromScreen.toggle()
}
}
}
}

The SilentModeView is a SwiftUI view responsible for displaying the iPhone silent mode animation. It uses several state variables (@State) to control the animation's various components.

Components of the Animation

Let’s break down each component of the iPhone silent mode animation and understand how they work together.

1. Bell View

The Rectangle view acts as the background for the bell icon.

Rectangle()
.foregroundColor(.white)
.frame(width: 220, height: 60)
.cornerRadius(30)

The rectangle has a white background color, a size of 220x60, and rounded corners with a radius of 30.

2. Silent and On/Off Stack

This stack contains the bell icon and the silent mode on/off text.

VStack {
HStack(spacing: 20) {
ZStack {
// Bell Icon
Image(systemName: "bell.fill")
.font(.largeTitle)
.foregroundColor(bellColor ? .gray : .red)
.rotationEffect(.degrees(bellRotate ? 0 : -25), anchor: .top)
.onAppear() {
withAnimation(.easeInOut(duration: 0.5).delay(2.3)) {
bellColor.toggle()
}

withAnimation(.interpolatingSpring(stiffness: 350, damping: 3).delay(2.3)) {
bellRotate.toggle()
}
}

// Slash
Rectangle()
.frame(width: 5, height: 40)
.foregroundColor(.gray)
.scaleEffect(x: 1, y: hideSlash ? 0 : 1, anchor: .topLeading)
.rotationEffect(.degrees(-40))
.onAppear() {
withAnimation(.easeOut(duration: 0.8).delay(2.1)) {
hideSlash.toggle()
}
}
}
// On/Off View
VStack {
Text("Silent Mode")
.foregroundColor(.black)
.opacity(0.6)
.fontWeight(.bold)
ZStack {
Text("Off")
.foregroundColor(.gray)
.fontWeight(.bold)
.opacity(onOff ? 1 : 0)
.onAppear() {
withAnimation(.easeOut(duration: 1.2).delay(2.1)) {
onOff.toggle()
}
}
Text("On")
.foregroundColor(.red)
.fontWeight(.bold)
.opacity(offOn ? 0 : 1)
.onAppear() {
withAnimation(.easeOut(duration: 1.2).delay(2.1)) {
offOn.toggle()
}
}
}
}
}
}

Inside the VStack, we have an HStack containing two components:

a. Bell Icon

The bell icon is displayed using the Image view with the "bell.fill" system name.

Image(systemName: "bell.fill")
.font(.largeTitle)
.foregroundColor(bellColor ? .gray : .red)
.rotationEffect(.degrees(bellRotate ? 0 : -25), anchor: .top)
.onAppear() {
withAnimation(.easeInOut(duration: 0.5).delay(2.3)) {
bellColor.toggle()
}

withAnimation(.interpolatingSpring(stiffness: 350, damping: 3).delay(2.3)) {
bellRotate.toggle()
}
}

The bell icon’s color is determined by the bellColor state variable, which toggles between gray and red. The bellicon also rotates based on the bellRotatestate variable, which toggles between -25 degrees and 0 degrees. These animations are triggered using the.onAppear` modifier with specific durations and delays.

b. Slash

The slash component is represented by a Rectangle view.

Rectangle()
.frame(width: 5, height: 40)
.foregroundColor(.gray)
.scaleEffect(x: 1, y: hideSlash ? 0 : 1, anchor: .topLeading)
.rotationEffect(.degrees(-40))
.onAppear() {
withAnimation(.easeOut(duration: 0.8).delay(2.1)) {
hideSlash.toggle()
}
}

The rectangle’s width and height are set to 5 and 40, respectively, and it is colored gray. The hideSlash state variable controls its visibility by scaling the height from 0 to 1. Additionally, the rectangle rotates by -40 degrees and animates using the .onAppear modifier.

3. On/Off View

The on/off text component is displayed using a ZStack with two Text views.

ZStack {
Text("Off")
.foregroundColor(.gray)
.fontWeight(.bold)
.opacity(onOff ? 1 : 0)
.onAppear() {
withAnimation(.easeOut(duration: 1.2).delay(2.1)) {
onOff.toggle()
}
}
Text("On")
.foregroundColor(.red)
.fontWeight(.bold)
.opacity(offOn ? 0 : 1)
.onAppear() {
withAnimation(.easeOut(duration: 1.2).delay(2.1)) {
offOn.toggle()
}
}
}

The Text("Off") view is initially visible (opacity set to 1) while the Text("On") view is hidden (opacity set to 0). The state variables onOff and offOn control the opacity of each text view, creating a smooth transition between the two. The .onAppear modifier triggers the animation with the specified duration and delay.

4. Animation Modifiers

To bring the entire animation together, we apply various animation modifiers to the top-level view.

.offset(y: hideFromScreen ? -UIScreen.main.bounds.height / 2.4 : -UIScreen.main.bounds.height / 1.8)
.onAppear() {
withAnimation(.easeInOut(duration: 0.5).delay(2)) {
hideFromScreen.toggle()
}
}

The .offset modifier animates the view's vertical position, moving it from a hidden position to the desired location on the screen. The hideFromScreen state variable controls the offset value based on the device's screen height.

Additionally, the .onAppear modifier triggers the animation when the view appears on the screen. It gradually reveals the silent mode animation by toggling the hideFromScreen state variable and applying an easing animation with a duration and delay.

Conclusion

In this article, we dissected the iPhone silent mode animation using SwiftUI. By understanding each component and its associated animation modifiers, you can create engaging and dynamic animations in your SwiftUI projects.

Remember to experiment with the provided code and customize it to suit your needs. SwiftUI provides a powerful framework for creating visually stunning animations, and the iPhone silent mode animation is just one example of its capabilities.

Happy animating! 🚀

We invite you to continue your journey of iOS discovery by following the Connect.iOS Instagram account, where you’ll find a treasure trove of amazing iOS content. Stay updated with the latest trends, tips, and tricks that will enhance your iOS development skills. Join the vibrant community and immerse yourself in the enchanting world of iOS.

Follow Connect.iOS on Instagram: Connect.iOS Instagram

Embark on your own odyssey of iOS development, experimenting with the various SwiftUI properties and values to create unique and mesmerizing animations. Unleash your creativity and let your imagination soar as you craft immersive user experiences that captivate and inspire. The possibilities are endless, and the journey is yours to embrace. Happy coding!

Note: Be sure to visit the Connect.iOS Instagram account at https://www.instagram.com/connect.ios/ for more amazing iOS content.

--

--

Rohit Saini

कर्म मुझे बांधता नहीं, क्योंकि मुझे कर्म के प्रतिफल की कोई इच्छा नहीं |