Skip to content

Instantly share code, notes, and snippets.

@iAmVishal16
Created March 24, 2024 17:19
Show Gist options
  • Select an option

  • Save iAmVishal16/0194d67aed1443684b0216a5b23add0f to your computer and use it in GitHub Desktop.

Select an option

Save iAmVishal16/0194d67aed1443684b0216a5b23add0f to your computer and use it in GitHub Desktop.
Unlocking SwiftUI ScrollView Paging: Dual Scroll View Sync Mechanisms
import SwiftUI
struct HCardsScrollView: View {
let colorSets: [Color] = [
.red, .green, .blue,
.yellow, .purple, .pink,
.accentColor, .black, .brown,
.cyan, .indigo, .teal,
.orange, .mint
]
@State private var selectedColor: Int? = 0
var body: some View {
GeometryReader { reader in
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack(spacing: 0) {
ForEach(colorSets.indices, id: \.self) { index in
let color = colorSets[index].opacity(0.8)
Rectangle()
.foregroundStyle(color)
.frame(width: reader.size.width, height: reader.size.height)
.tag(index)
}
}
.scrollTargetLayout()
}
.scrollTargetBehavior(.paging)
.scrollPosition(id: $selectedColor)
}
.edgesIgnoringSafeArea(.all)
// MARK: - Fast Scroll container
.overlay (alignment: .bottom) {
FastScrollView(colors: colorSets, selectedColor: $selectedColor)
.frame(height: 96)
.safeAreaPadding(.horizontal, 16)
}
}
}
#Preview {
HCardsScrollView()
}
struct FastScrollView: View {
var colors: [Color]
@Binding var selectedColor: Int?
var body: some View {
ZStack {
ScrollViewReader { reader in
ScrollView(.horizontal, showsIndicators: false) {
LazyHStack {
ForEach(colors.indices, id: \.self) { index in
let color = colors[index].opacity(0.8)
Circle()
.foregroundStyle(color)
.frame(width: 80, height: 80)
.background(
Circle()
.stroke(lineWidth: selectedColor == index ? 8 : 0)
.foregroundStyle(Material.bar)
)
.padding(.bottom, 4)
.padding(.leading, 4)
.tag(index)
.onTapGesture {
withAnimation(.spring) {
self.selectedColor = index
reader.scrollTo(index, anchor: .center)
}
}
.scrollTransition(.animated.threshold(.visible(0.9))) { content, phase in
content
.opacity(phase.isIdentity ? 1 : 0.5)
.scaleEffect(phase.isIdentity ? 1 : 0.55)
}
}
}
.scrollTargetLayout()
}
.scrollTargetBehavior(.viewAligned)
.onChange(of: selectedColor, { oldValue, newValue in
withAnimation(.spring) {
reader.scrollTo(selectedColor ?? 0, anchor: .center)
}
})
}
}
}
}
#Preview {
FastScrollView(colors: [
.red, .green, .blue,
.yellow, .purple, .pink,
.accentColor, .black, .brown,
.cyan, .indigo, .teal,
.orange, .mint
], selectedColor: .constant(0))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment