A performant UIKit shimmer effect for text loading states. Adapted from the public domain ShimmerSwift library with bug fixes, modernized Swift concurrency support, and a cleaner API.
Add ShimmerView to your project via Swift Package Manager:
dependencies:[.package(url:"https://github.com/gtokman/ShimmerView.git", from:"1.0.0")]Add a label (or any content) to the contentView, then set isShimmering = true. The shimmer sweeps across as a translucency mask — your text stays fully readable while a highlight glides through it.
import ShimmerView
letshimmer=ShimmerView()
shimmer.translatesAutoresizingMaskIntoConstraints =falseletlabel=UILabel()
label.text ="Thinking..."
label.textColor =.white
label.font =.systemFont(ofSize:16)
label.numberOfLines =0
label.translatesAutoresizingMaskIntoConstraints =false
shimmer.contentView.addSubview(label)NSLayoutConstraint.activate([
label.topAnchor.constraint(equalTo: shimmer.contentView.topAnchor),
label.leadingAnchor.constraint(equalTo: shimmer.contentView.leadingAnchor),
label.trailingAnchor.constraint(equalTo: shimmer.contentView.trailingAnchor),
label.bottomAnchor.constraint(equalTo: shimmer.contentView.bottomAnchor),])
shimmer.isShimmering =trueletshimmer=ShimmerView()
shimmer.translatesAutoresizingMaskIntoConstraints =falseletlabel=UILabel()
label.text ="Loading message content\nThis might take a moment\nPlease wait"
label.textColor =.white
label.font =.systemFont(ofSize:16)
label.numberOfLines =0
label.translatesAutoresizingMaskIntoConstraints =false
shimmer.contentView.addSubview(label)NSLayoutConstraint.activate([
label.topAnchor.constraint(equalTo: shimmer.contentView.topAnchor),
label.leadingAnchor.constraint(equalTo: shimmer.contentView.leadingAnchor),
label.trailingAnchor.constraint(equalTo: shimmer.contentView.trailingAnchor),
label.bottomAnchor.constraint(equalTo: shimmer.contentView.bottomAnchor),])
shimmer.isShimmering =true
// Stop when content loads
shimmer.isShimmering =falseletshimmer=ShimmerView()
// Set individual properties
shimmer.shimmerSpeed =300
shimmer.shimmerDirection =.left
shimmer.shimmerAnimationOpacity =0.3
// Or replace the full configuration
varconfig=ShimmerConfiguration()
config.speed =300
config.direction =.left
config.animationOpacity =0.3
config.pauseDuration =0.6
shimmer.configuration = config| Property | Default | Description |
|---|---|---|
speed | 600 | Speed in points per second |
direction | .right | Sweep direction (.right, .left, .up, .down) |
highlightLength | 0.42 | Highlight band as a fraction of content size [0, 1] |
pauseDuration | 0.49 | Pause between repetitions (seconds) |
animationOpacity | 0.57 | Opacity of the dimmed region |
baseOpacity | 1.0 | Opacity of the bright region |
beginFadeDuration | 0.1 | Fade-in duration when shimmer starts |
endFadeDuration | 0.3 | Fade-out duration when shimmer stops |
The Example/ directory contains a demo app with interactive sliders for every configuration property. Generate the Xcode project with XcodeGen:
brew install xcodegen
xcodegen generate
open ShimmerViewExample.xcodeproj- iOS 15+
- Swift 6.0+
MIT