Skip to content

Instantly share code, notes, and snippets.

@borisdipner
Last active October 27, 2022 20:08
Show Gist options
  • Save borisdipner/11509b51f00eb5a16dfff196521736b3 to your computer and use it in GitHub Desktop.
Save borisdipner/11509b51f00eb5a16dfff196521736b3 to your computer and use it in GitHub Desktop.
struct AdaptivePagingScrollView: View {
/// { * * * States * * * }
/// { * * * Functions * * * }
var body: some View {
// 01
GeometryReader { viewGeometry in
HStack(alignment: .center, spacing: itemSpacing) {
ForEach(items.indices, id: \.self) { itemIndex in
items[itemIndex].frame(width: itemWidth)
}
}
}
.onAppear { // 02
currentScrollOffset = countOffset(for: currentPageIndex)
}
.background(Color.black.opacity(0.00001)) // hack - this allows gesture recognizing even when background is transparent
.frame(width: contentWidth)
.offset(x: self.currentScrollOffset, y: 0)
.simultaneousGesture( // 03
DragGesture(minimumDistance: 1, coordinateSpace: .local)
.onChanged { value in // 04
gestureDragOffset = value.translation.width
currentScrollOffset = countCurrentScrollOffset()
}
.onEnded { value in // 05
let cleanOffset = (value.predictedEndTranslation.width - gestureDragOffset)
let velocityDiff = cleanOffset * scrollDampingFactor
var newPageIndex = countPageIndex(for: currentScrollOffset + velocityDiff)
let currentItemOffset = CGFloat(currentPageIndex) * (itemWidth + itemPadding)
if currentScrollOffset < -(currentItemOffset),
newPageIndex == currentPageIndex {
newPageIndex += 1
}
gestureDragOffset = 0
// 06
withAnimation(.interpolatingSpring(mass: 0.1,
stiffness: 20,
damping: 1.5,
initialVelocity: 0)) {
self.currentPageIndex = newPageIndex
self.currentScrollOffset = self.countCurrentScrollOffset()
}
}
)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment