@@ -459,18 +459,20 @@ extension AnyListLayout
459
459
func onDidEndDraggingTargetContentOffset(
460
460
for targetContentOffset : CGPoint ,
461
461
velocity : CGPoint ,
462
- visibleContentSize : CGSize
462
+ visibleContentFrame : CGRect
463
463
) -> CGPoint ?
464
464
{
465
465
guard self . pagingBehavior != . none else { return nil }
466
-
466
+
467
467
guard let item = self . itemToScrollToOnDidEndDragging (
468
468
after: targetContentOffset,
469
- velocity: velocity
469
+ velocity: velocity,
470
+ visibleContentFrame: visibleContentFrame
470
471
) else {
471
472
return nil
472
473
}
473
474
475
+ let visibleContentSize = visibleContentFrame. size
474
476
let padding = self . bounds? . padding ?? . zero
475
477
476
478
switch self . pagingBehavior {
@@ -493,39 +495,84 @@ extension AnyListLayout
493
495
494
496
func itemToScrollToOnDidEndDragging(
495
497
after contentOffset : CGPoint ,
496
- velocity : CGPoint
498
+ velocity : CGPoint ,
499
+ visibleContentFrame: CGRect
497
500
) -> ListLayoutContent . ContentItem ?
498
501
{
499
- let rect : CGRect = self . rectForFindingItemToScrollToOnDidEndDragging (
500
- after: contentOffset,
501
- velocity: velocity
502
- )
502
+ let rect : CGRect
503
+ if scrollViewProperties. pageScrollingBehavior == . peek {
504
+ /// When peeking, the visible items are the only items considered for the page offest.
505
+ rect = visibleContentFrame
506
+ } else {
507
+ rect = self . rectForFindingItemToScrollToOnDidEndDragging (
508
+ after: contentOffset,
509
+ velocity: velocity
510
+ )
511
+ }
503
512
504
513
let scrollDirection = ScrollVelocityDirection ( direction. y ( for: velocity) )
505
514
506
515
let items = self . content. content (
507
516
in: rect,
508
517
alwaysIncludeOverscroll: false ,
509
518
includeUnpopulated: false
510
- ) . sorted { lhs, rhs in
511
- switch scrollDirection {
512
- case . forward:
513
- return direction. minY ( for: lhs. defaultFrame) < direction. minY ( for: rhs. defaultFrame)
514
- case . backward:
515
- return direction. maxY ( for: lhs. defaultFrame) > direction. maxY ( for: rhs. defaultFrame)
516
- }
517
- }
518
-
519
- return items. first { item in
520
- let edge = direction. minY ( for: item. defaultFrame)
521
- let offset = direction. y ( for: contentOffset)
519
+ )
520
+
521
+ if scrollViewProperties. pageScrollingBehavior == . peek {
522
+ let mainAxisVelocity = direction. switch (
523
+ vertical: { velocity. y } ,
524
+ horizontal: { velocity. x }
525
+ )
522
526
523
- switch scrollDirection {
524
- case . forward:
525
- return edge >= offset
526
- case . backward:
527
- return edge <= offset
527
+ if mainAxisVelocity == 0 {
528
+ /// When the items are being held still with custom paging, bias the most visible item.
529
+ return items
530
+ . sorted { lhs, rhs in
531
+ lhs. percentageVisible ( inside: visibleContentFrame) > rhs. percentageVisible ( inside: visibleContentFrame)
532
+ }
533
+ . first
534
+ } else {
535
+ return items
536
+ /// Sort items in ascending order, based on their position along the primary axis.
537
+ . sorted { lhs, rhs in
538
+ direction. minY ( for: lhs. defaultFrame) > direction. minY ( for: rhs. defaultFrame)
539
+ }
540
+ /// Using the visible sorted items, return the first that has a minimum edge outside the target offset.
541
+ . first { item in
542
+ let edge = direction. minY ( for: item. defaultFrame)
543
+ let offset = direction. y ( for: contentOffset)
544
+
545
+ switch scrollDirection {
546
+ case . forward:
547
+ return edge >= offset
548
+ case . backward:
549
+ return edge <= offset
550
+ }
551
+ }
528
552
}
553
+ } else {
554
+ return items
555
+ /// Sort items based on their position on the primary axis, in ascending order.
556
+ . sorted { lhs, rhs in
557
+ switch scrollDirection {
558
+ case . forward:
559
+ return direction. minY ( for: lhs. defaultFrame) < direction. minY ( for: rhs. defaultFrame)
560
+ case . backward:
561
+ return direction. maxY ( for: lhs. defaultFrame) > direction. maxY ( for: rhs. defaultFrame)
562
+ }
563
+ }
564
+ /// Using the sorted items, return the first has has a min edge outside the offset.
565
+ . first { item in
566
+ let edge = direction. minY ( for: item. defaultFrame)
567
+ let offset = direction. y ( for: contentOffset)
568
+
569
+ switch scrollDirection {
570
+ case . forward:
571
+ return edge >= offset
572
+ case . backward:
573
+ return edge <= offset
574
+ }
575
+ }
529
576
}
530
577
}
531
578
0 commit comments