@@ -262,6 +262,11 @@ public struct Carousel<Content>: View where Content: View {
262
262
. onPreferenceChange ( CarouselContentSizePreferenceKey . self) { size in
263
263
DispatchQueue . main. async {
264
264
self . contentSize = size
265
+ let finalX = self . calculateContentOffsetX ( from: self . contentOffset. x)
266
+ if abs ( finalX. distance ( to: self . contentOffset. x) ) > 0.1 {
267
+ self . contentOffset. x = finalX
268
+ self . preContentOffset = self . contentOffset
269
+ }
265
270
}
266
271
}
267
272
. contentShape ( Rectangle ( ) )
@@ -272,17 +277,8 @@ public struct Carousel<Content>: View where Content: View {
272
277
}
273
278
. onEnded { value in
274
279
withAnimation ( . easeOut( duration: 0.5 ) ) {
275
- let maxX = max ( 0 , contentSize. width - self . viewSize. width)
276
280
let expectedX = max ( 0 , preContentOffset. x + ( self . layoutDirection == . leftToRight ? - 1 : 1 ) * value. predictedEndTranslation. width)
277
- var finalX = min ( maxX, expectedX)
278
-
279
- if self . isSnapping {
280
- let itemWidth : CGFloat = ( viewSize. width - self . contentInsets. horizontal - CGFloat( self . numberOfColumns + 2 ) * self . spacing) / CGFloat( self . numberOfColumns)
281
- let index = ( ( expectedX - self . contentInsets. leading) / ( itemWidth + self . spacing) ) . rounded ( )
282
- let idealX = index * itemWidth + max( 0 , index - 1 ) * self . spacing + ( index == 0 ? 0 : self . contentInsets. leading)
283
- finalX = max ( 0 , min ( maxX, idealX) )
284
- }
285
-
281
+ let finalX = self . calculateContentOffsetX ( from: expectedX)
286
282
self . contentOffset. x = finalX
287
283
self . preContentOffset = self . contentOffset
288
284
}
@@ -293,9 +289,28 @@ public struct Carousel<Content>: View where Content: View {
293
289
. onPreferenceChange ( CarouselSizePreferenceKey . self) { size in
294
290
DispatchQueue . main. async {
295
291
self . viewSize = size
292
+ let finalX = self . calculateContentOffsetX ( from: self . contentOffset. x)
293
+ if abs ( finalX. distance ( to: self . contentOffset. x) ) > 0.1 {
294
+ self . contentOffset. x = finalX
295
+ self . preContentOffset = self . contentOffset
296
+ }
296
297
}
297
298
}
298
299
}
300
+
301
+ func calculateContentOffsetX( from x: CGFloat ) -> CGFloat {
302
+ let maxX = max ( 0 , contentSize. width - self . viewSize. width)
303
+ var finalX = min ( maxX, x)
304
+
305
+ if self . isSnapping {
306
+ let itemWidth : CGFloat = ( viewSize. width - self . contentInsets. horizontal - CGFloat( self . numberOfColumns + 2 ) * self . spacing) / CGFloat( self . numberOfColumns)
307
+ let index = ( ( x - self . contentInsets. leading) / ( itemWidth + self . spacing) ) . rounded ( )
308
+ let idealX = index * itemWidth + max( 0 , index - 1 ) * self . spacing + ( index == 0 ? 0 : self . contentInsets. leading)
309
+ finalX = max ( 0 , min ( maxX, idealX) )
310
+ }
311
+
312
+ return finalX
313
+ }
299
314
}
300
315
301
316
#Preview {
0 commit comments