Library / Pickers, sliders & steppers

Zoom / level change

Pinch-zoom that steps through discrete levels (1x, 2x, 3x) — a tick per level, camera-app style.

0ms 100ms 200ms 300ms 400ms
Feel
One .levelChange tick per zoom step; boundaries feel like gentle gear changes.
APIs
.sensoryFeedback(.levelChange)MagnifyGesture
Minimum OS
iOS 17+
Raw .md
SwiftUI (iOS 17+)
import SwiftUI

struct SteppedZoomView: View {
    @State private var scale: CGFloat = 1
    @State private var committed: CGFloat = 1
    private var level: Int { Int(scale.rounded()) } // 1x, 2x, 3x…

    var body: some View {
        Image(systemName: "photo")
            .font(.system(size: 80))
            .frame(maxWidth: .infinity, maxHeight: 300)
            .scaleEffect(scale)
            .gesture(
                MagnifyGesture()
                    .onChanged { value in
                        scale = min(4, max(1, committed * value.magnification))
                    }
                    .onEnded { _ in
                        committed = CGFloat(level)     // settle on a step
                        withAnimation(.snappy) { scale = committed }
                    }
            )
            .sensoryFeedback(.levelChange, trigger: level)
            .overlay(alignment: .bottom) {
                Text("\(level)x").font(.caption.bold()).padding(6)
                    .background(.thinMaterial, in: Capsule())
            }
    }
}
Copied