SwiftUI and UIKit animated controls using Lottie animations for rich interactive experiences, including buttons and switches with state-driven animation playback.
UIKit control that plays animations in response to user interaction, with customizable animation ranges for different button states.
/**
* Interactive button that plays animations on user interaction
* Inherits from AnimatedControl with button-specific behavior
*/
open class AnimatedButton: AnimatedControl {
// MARK: - Initializers
/**
* Initialize with animation and configuration
* @param animation - Lottie animation for the button
* @param configuration - Lottie configuration settings
*/
public init(
animation: LottieAnimation?,
configuration: LottieConfiguration = .shared
)
/**
* Initialize empty button (animation set later)
*/
public override init()
/**
* Initialize from Interface Builder
*/
required public init?(coder aDecoder: NSCoder)
// MARK: - Properties
/**
* Closure called when button is pressed/clicked
* Set this to handle button tap events
*/
public var performAction: (() -> Void)?
// MARK: - Inherited from AnimatedControl
/** The underlying animation view */
public var animationView: LottieAnimationView { get }
/** Current animation being displayed */
public var animation: LottieAnimation? { get set }
/**
* Set animation range for specific control events
* @param range - Progress range to play (0.0 to 1.0)
* @param event - UIControl event to trigger range
*/
public func setPlayRange(fromProgress: AnimationProgressTime, toProgress: AnimationProgressTime, event: UIControl.Event)
/**
* Set animation range using frame numbers
* @param fromFrame - Starting frame
* @param toFrame - Ending frame
* @param event - UIControl event to trigger range
*/
public func setPlayRange(fromFrame: AnimationFrameTime, toFrame: AnimationFrameTime, event: UIControl.Event)
/**
* Set animation range using marker names
* @param fromMarker - Starting marker name
* @param toMarker - Ending marker name
* @param event - UIControl event to trigger range
*/
public func setPlayRange(fromMarker: String, toMarker: String, event: UIControl.Event)
}Usage Examples:
import Lottie
import UIKit
// Create animated button
let button = AnimatedButton(animation: LottieAnimation.named("button-animation"))
// Set action handler
button.performAction = {
print("Button was pressed!")
// Handle button press
}
// Configure animation ranges for different states
button.setPlayRange(
fromProgress: 0.0,
toProgress: 0.5,
event: .touchDown
)
button.setPlayRange(
fromProgress: 0.5,
toProgress: 1.0,
event: .touchUpInside
)
// Add to view
view.addSubview(button)
button.frame = CGRect(x: 50, y: 100, width: 100, height: 100)UIKit switch control with on/off states, playing different animation ranges based on the current state.
/**
* Interactive switch with 'On' and 'Off' states
* Toggles between states with appropriate animations
*/
open class AnimatedSwitch: AnimatedControl {
// MARK: - Initializers
/**
* Initialize with animation and configuration
* @param animation - Lottie animation for the switch
* @param configuration - Lottie configuration settings
*/
public init(
animation: LottieAnimation?,
configuration: LottieConfiguration = .shared
)
/**
* Initialize empty switch (animation set later)
*/
public override init()
/**
* Initialize from Interface Builder
*/
required public init?(coder aDecoder: NSCoder)
// MARK: - Properties
/**
* Current switch state
* true = on, false = off
*/
public var isOn: Bool { get set }
/**
* Progress value for 'On' state (0.0 to 1.0)
* Animation will play to this progress when switch is on
*/
public var onProgressTime: AnimationProgressTime { get set }
/**
* Progress value for 'Off' state (0.0 to 1.0)
* Animation will play to this progress when switch is off
*/
public var offProgressTime: AnimationProgressTime { get set }
/**
* Whether to animate when programmatically changing animation
* Default: true
*/
public var animateUpdateWhenChangingAnimation: Bool { get set }
// MARK: - Methods
/**
* Set switch state with optional animation
* @param isOn - New switch state
* @param animated - Whether to animate the transition
*/
public func setIsOn(_ isOn: Bool, animated: Bool)
/**
* Set progress values for on/off states
* @param on - Progress when switch is on (0.0 to 1.0)
* @param off - Progress when switch is off (0.0 to 1.0)
*/
public func setProgressForState(on: AnimationProgressTime, off: AnimationProgressTime)
}Usage Examples:
import Lottie
import UIKit
// Create animated switch
let animatedSwitch = AnimatedSwitch(animation: LottieAnimation.named("toggle-switch"))
// Configure on/off progress values
animatedSwitch.setProgressForState(on: 1.0, off: 0.0)
// Set initial state
animatedSwitch.setIsOn(false, animated: false)
// Listen for value changes
animatedSwitch.addTarget(self, action: #selector(switchValueChanged), for: .valueChanged)
// Add to view
view.addSubview(animatedSwitch)
animatedSwitch.frame = CGRect(x: 50, y: 200, width: 100, height: 60)
@objc func switchValueChanged(_ sender: AnimatedSwitch) {
print("Switch is now: \\(sender.isOn ? "ON" : "OFF")")
}SwiftUI wrapper for AnimatedButton providing declarative interface with closure-based actions.
/**
* SwiftUI wrapper for AnimatedButton
* Provides declarative interface for animated buttons
*/
public struct LottieButton: View {
// MARK: - Initializers
/**
* Initialize with animation and action
* @param animation - Lottie animation for button
* @param action - Closure to execute on button press
*/
public init(animation: LottieAnimation?, action: @escaping () -> Void)
// MARK: - View Protocol
public var body: some View { get }
// MARK: - Configuration Methods
/**
* Configure the underlying AnimatedButton
* @param configure - Configuration closure
* @returns Modified LottieButton
*/
public func configure(_ configure: @escaping (AnimatedButton) -> Void) -> Self
/**
* Set animation speed
* @param speed - Animation playback speed multiplier
* @returns Modified LottieButton
*/
public func animationSpeed(_ speed: CGFloat) -> Self
/**
* Set loop mode for button animations
* @param loopMode - Loop behavior for animations
* @returns Modified LottieButton
*/
public func loopMode(_ loopMode: LottieLoopMode) -> Self
}Usage Examples:
import SwiftUI
import Lottie
struct ContentView: View {
var body: some View {
VStack(spacing: 20) {
// Basic animated button
LottieButton(animation: .named("like-button")) {
print("Like button pressed!")
}
.frame(width: 80, height: 80)
// Configured animated button
LottieButton(animation: .named("submit-button")) {
submitForm()
}
.animationSpeed(1.5)
.configure { button in
button.setPlayRange(
fromProgress: 0.0,
toProgress: 0.5,
event: .touchDown
)
button.setPlayRange(
fromProgress: 0.5,
toProgress: 1.0,
event: .touchUpInside
)
}
.frame(width: 120, height: 50)
}
}
func submitForm() {
// Handle form submission
}
}SwiftUI wrapper for AnimatedSwitch with binding support for reactive state management.
/**
* SwiftUI wrapper for AnimatedSwitch
* Provides declarative interface with binding support
*/
public struct LottieSwitch: View {
// MARK: - Initializers
/**
* Initialize with animation
* @param animation - Lottie animation for switch
*/
public init(animation: LottieAnimation?)
// MARK: - View Protocol
public var body: some View { get }
// MARK: - Configuration Methods
/**
* Bind switch state to external value
* @param isOn - Binding to boolean state
* @returns Modified LottieSwitch
*/
public func isOn(_ isOn: Binding<Bool>) -> Self
/**
* Configure the underlying AnimatedSwitch
* @param configure - Configuration closure
* @returns Modified LottieSwitch
*/
public func configure(_ configure: @escaping (AnimatedSwitch) -> Void) -> Self
/**
* Set animation speed
* @param speed - Animation playback speed multiplier
* @returns Modified LottieSwitch
*/
public func animationSpeed(_ speed: CGFloat) -> Self
}Usage Examples:
import SwiftUI
import Lottie
struct SettingsView: View {
@State private var notificationsEnabled = false
@State private var darkModeEnabled = true
var body: some View {
VStack(spacing: 30) {
// Basic switch with binding
HStack {
Text("Notifications")
Spacer()
LottieSwitch(animation: .named("notification-toggle"))
.isOn($notificationsEnabled)
.frame(width: 60, height: 40)
}
// Configured switch
HStack {
Text("Dark Mode")
Spacer()
LottieSwitch(animation: .named("dark-mode-toggle"))
.isOn($darkModeEnabled)
.animationSpeed(0.8)
.configure { switch in
switch.setProgressForState(on: 1.0, off: 0.0)
switch.animateUpdateWhenChangingAnimation = true
}
.frame(width: 80, height: 50)
}
}
.padding()
}
}Base class for creating custom animated controls with state-driven layer visibility and animation playback.
/**
* Base class for animated controls
* Provides foundation for interactive Lottie-based UI elements
*/
open class AnimatedControl: UIControl {
// MARK: - Properties
/** The underlying LottieAnimationView */
public var animationView: LottieAnimationView { get }
/** Current animation being displayed */
public var animation: LottieAnimation? { get set }
// MARK: - Initializers
/**
* Initialize with animation and configuration
* Note: Do not initialize directly, intended to be subclassed
*/
public init(animation: LottieAnimation?, configuration: LottieConfiguration = .shared)
// MARK: - Animation Range Configuration
/**
* Set animation range for specific control events
* @param fromProgress - Starting progress (0.0 to 1.0)
* @param toProgress - Ending progress (0.0 to 1.0)
* @param event - UIControl event to trigger this range
*/
public func setPlayRange(
fromProgress: AnimationProgressTime,
toProgress: AnimationProgressTime,
event: UIControl.Event
)
/**
* Set animation range using frame numbers
* @param fromFrame - Starting frame number
* @param toFrame - Ending frame number
* @param event - UIControl event to trigger this range
*/
public func setPlayRange(
fromFrame: AnimationFrameTime,
toFrame: AnimationFrameTime,
event: UIControl.Event
)
/**
* Set animation range using marker names
* @param fromMarker - Starting marker name
* @param toMarker - Ending marker name
* @param event - UIControl event to trigger this range
*/
public func setPlayRange(
fromMarker: String,
toMarker: String,
event: UIControl.Event
)
// MARK: - Layer State Management
/**
* Set layer name for specific control state
* @param layerName - Name of layer to show for this state
* @param state - UIControl state
*/
public func setLayer(named layerName: String, forState state: UIControl.State)
// MARK: - Override Points
/**
* Called when animation property is set
* Override in subclasses for custom behavior
*/
open func animationDidSet()
}This base class enables creation of custom animated controls by subclassing and implementing specific interaction behaviors.