@onekeyfe/react-native-pager-view 3.0.166 → 3.0.168
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -695,13 +695,13 @@ private class NativeScrollerRefreshLayout(context: Context) : SwipeRefreshLayout
|
|
|
695
695
|
ancestor = ancestor.parent as? View
|
|
696
696
|
}
|
|
697
697
|
intercepted = false
|
|
698
|
-
} else if (event.actionMasked == MotionEvent.ACTION_MOVE && (!smoothPagerGesture || !vertical)) {
|
|
698
|
+
} else if (event.actionMasked == MotionEvent.ACTION_MOVE && (!smoothPagerGesture || (!vertical && !horizontal))) {
|
|
699
699
|
val dx = abs(event.x - downX)
|
|
700
700
|
val dy = abs(event.y - downY)
|
|
701
701
|
if (smoothPagerGesture && dy > slop && dy > dx) {
|
|
702
702
|
vertical = true
|
|
703
703
|
horizontal = false
|
|
704
|
-
} else if (
|
|
704
|
+
} else if ((if (smoothPagerGesture) dx >= 32f * resources.displayMetrics.density else dx > slop) && dx > dy) {
|
|
705
705
|
horizontal = true
|
|
706
706
|
}
|
|
707
707
|
}
|
package/docs/SPEC.md
CHANGED
|
@@ -244,9 +244,19 @@ of the refresh boundary. Dispatch MUST still observe child-owned movement; only
|
|
|
244
244
|
a confirmed vertical Smooth Home gesture may release the viewport's child
|
|
245
245
|
interception prohibition. Pending and horizontal movement MUST preserve it.
|
|
246
246
|
|
|
247
|
+
In smooth-header mode, Android's NativeScroller refresh boundary MUST retain a
|
|
248
|
+
confirmed horizontal or vertical direction until the touch sequence ends or is
|
|
249
|
+
cancelled. It MUST classify MOVE direction only while neither direction is confirmed,
|
|
250
|
+
and horizontal confirmation MUST include the 32 dp boundary, matching the
|
|
251
|
+
viewport. Later vertical movement after confirmed horizontal intent MUST NOT
|
|
252
|
+
start a refresh gesture. Non-smooth refresh direction behavior remains unchanged.
|
|
253
|
+
|
|
247
254
|
iOS nested horizontal ownership MUST include enabled nonpaging horizontal-only
|
|
248
255
|
ScrollViews, with content wider than bounds and no vertical content overflow.
|
|
249
256
|
Both pan holding and failure dependencies MUST use the same eligibility. A
|
|
257
|
+
failure dependency on the Pager guard MUST apply only to the horizontal pan;
|
|
258
|
+
independent non-pan recognizers, including stationary native long presses, MUST
|
|
259
|
+
remain able to recognize before finger-up while Pager intent is pending. A
|
|
250
260
|
second touch in the pending Pager guard fails recognition; an already active
|
|
251
261
|
Pager guard cancels and restores each held pan's original minimum touch count.
|
|
252
262
|
|
|
@@ -199,9 +199,7 @@ static void RNCGuardNestedHorizontalPans(UIView *view, UIGestureRecognizer *guar
|
|
|
199
199
|
if ([view isKindOfClass:UIScrollView.class]) {
|
|
200
200
|
UIScrollView *scroll = (UIScrollView *)view;
|
|
201
201
|
if (RNCIsEnabledHorizontalScrollOwner(scroll)) {
|
|
202
|
-
|
|
203
|
-
[gesture requireGestureRecognizerToFail:guard];
|
|
204
|
-
}
|
|
202
|
+
[scroll.panGestureRecognizer requireGestureRecognizerToFail:guard];
|
|
205
203
|
}
|
|
206
204
|
}
|
|
207
205
|
for (UIView *child in view.subviews) RNCGuardNestedHorizontalPans(child, guard);
|
|
@@ -165,7 +165,9 @@ typedef struct __IOHIDEvent *RNCTestHIDEventRef;
|
|
|
165
165
|
[_window sendEvent:_event];
|
|
166
166
|
if (phase == UITouchPhaseEnded || phase == UITouchPhaseCancelled) {
|
|
167
167
|
[_activeTouches removeObjectIdenticalTo:changed];
|
|
168
|
-
|
|
168
|
+
// A finished finger must not be delivered again when another finger ends.
|
|
169
|
+
[_event _clearTouches];
|
|
170
|
+
for (UITouch *touch in _activeTouches) [_event _addTouch:touch forDelayedDelivery:NO];
|
|
169
171
|
}
|
|
170
172
|
}
|
|
171
173
|
|
|
@@ -621,6 +623,7 @@ typedef struct __IOHIDEvent *RNCTestHIDEventRef;
|
|
|
621
623
|
@property (nonatomic, strong) RNCCollapsiblePagerViewComponentView *pager;
|
|
622
624
|
@property (nonatomic, strong) RNCSynthesizedTouchDriver *driver;
|
|
623
625
|
@property (nonatomic, strong) UIView *firstPage;
|
|
626
|
+
@property (nonatomic) NSUInteger longPressBegins;
|
|
624
627
|
@end
|
|
625
628
|
|
|
626
629
|
@implementation RNCCollapsiblePagerPressCancellationDeliveryTests
|
|
@@ -809,4 +812,111 @@ typedef struct __IOHIDEvent *RNCTestHIDEventRef;
|
|
|
809
812
|
XCTAssertEqualObjects(self.handler.events, (@[@"began", @"moved", @"ended"]));
|
|
810
813
|
}
|
|
811
814
|
|
|
815
|
+
- (UIScrollView *)mountNestedHorizontalScrollView
|
|
816
|
+
{
|
|
817
|
+
UIScrollView *vertical = [[UIScrollView alloc] initWithFrame:self.firstPage.bounds];
|
|
818
|
+
vertical.contentSize = CGSizeMake(CGRectGetWidth(vertical.bounds), 1800);
|
|
819
|
+
[self.firstPage addSubview:vertical];
|
|
820
|
+
UIScrollView *horizontal = [[UIScrollView alloc] initWithFrame:CGRectMake(40, 350, 300, 120)];
|
|
821
|
+
horizontal.contentSize = CGSizeMake(900, 120);
|
|
822
|
+
horizontal.contentOffset = CGPointMake(200, 0);
|
|
823
|
+
[vertical addSubview:horizontal];
|
|
824
|
+
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
|
|
825
|
+
initWithTarget:self action:@selector(nestedLongPress:)];
|
|
826
|
+
longPress.minimumPressDuration = 0.1;
|
|
827
|
+
[horizontal addGestureRecognizer:longPress];
|
|
828
|
+
// Re-run the production attachment path after the descendant mounts.
|
|
829
|
+
((void (*)(id, SEL))objc_msgSend)(self.pager, NSSelectorFromString(@"attachScrollObserverForCurrentPage"));
|
|
830
|
+
[self.window layoutIfNeeded];
|
|
831
|
+
[self drainMainQueue];
|
|
832
|
+
XCTAssertEqual([self.pager valueForKey:@"observedScrollView"], vertical);
|
|
833
|
+
return horizontal;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
- (void)nestedLongPress:(UILongPressGestureRecognizer *)recognizer
|
|
837
|
+
{
|
|
838
|
+
if (recognizer.state == UIGestureRecognizerStateBegan) self.longPressBegins += 1;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
- (CGPoint)pressPointInNestedScrollView:(UIScrollView *)scroll
|
|
842
|
+
{
|
|
843
|
+
CGPoint point = [scroll convertPoint:CGPointMake(scroll.contentOffset.x + 150, 60) toView:self.window];
|
|
844
|
+
XCTAssertEqual([self.window hitTest:point withEvent:nil], scroll);
|
|
845
|
+
return point;
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
- (void)testNestedStationaryNativeLongPressRecognizesBeforeFingerUp
|
|
849
|
+
{
|
|
850
|
+
UIScrollView *scroll = [self mountNestedHorizontalScrollView];
|
|
851
|
+
UITouch *touch = [self.driver beginAt:[self pressPointInNestedScrollView:scroll]];
|
|
852
|
+
UIGestureRecognizer *guard = [self.pager valueForKey:@"verticalPagerGesture"];
|
|
853
|
+
XCTAssertEqual(guard.state, UIGestureRecognizerStatePossible);
|
|
854
|
+
XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 2);
|
|
855
|
+
XCTestExpectation *hold = [self expectationWithDescription:@"stationary finger held"];
|
|
856
|
+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)),
|
|
857
|
+
dispatch_get_main_queue(), ^{ [hold fulfill]; });
|
|
858
|
+
[self waitForExpectations:@[hold] timeout:2];
|
|
859
|
+
// The real UIKit target action must arrive while the finger is still down.
|
|
860
|
+
XCTAssertEqual(self.longPressBegins, 1);
|
|
861
|
+
XCTAssertEqual(touch.phase, UITouchPhaseBegan);
|
|
862
|
+
XCTAssertEqual(guard.state, UIGestureRecognizerStatePossible);
|
|
863
|
+
[self.driver end:touch];
|
|
864
|
+
XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 1);
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
- (void)testNestedHorizontalPanConsumesConfirmedHorizontalDrag
|
|
868
|
+
{
|
|
869
|
+
UIScrollView *scroll = [self mountNestedHorizontalScrollView];
|
|
870
|
+
CGPoint point = [self pressPointInNestedScrollView:scroll];
|
|
871
|
+
CGFloat originalOffset = scroll.contentOffset.x;
|
|
872
|
+
UITouch *touch = [self.driver beginAt:point];
|
|
873
|
+
for (NSInteger step = 1; step <= 10; ++step) {
|
|
874
|
+
[self.driver move:touch to:CGPointMake(point.x - 12 * step, point.y)];
|
|
875
|
+
}
|
|
876
|
+
XCTAssertTrue(scroll.isDragging);
|
|
877
|
+
XCTAssertGreaterThan(scroll.contentOffset.x, originalOffset);
|
|
878
|
+
UIScrollView *pager = [self.pager valueForKey:@"pagerScrollView"];
|
|
879
|
+
XCTAssertFalse(pager.isDragging);
|
|
880
|
+
XCTAssertEqual(self.longPressBegins, 0);
|
|
881
|
+
[self.driver end:touch];
|
|
882
|
+
XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 1);
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
- (void)testNestedPendingHorizontalStartCanBecomeVertical
|
|
886
|
+
{
|
|
887
|
+
UIScrollView *scroll = [self mountNestedHorizontalScrollView];
|
|
888
|
+
CGPoint point = [self pressPointInNestedScrollView:scroll];
|
|
889
|
+
UITouch *touch = [self.driver beginAt:point];
|
|
890
|
+
[self.driver move:touch to:CGPointMake(point.x - 8, point.y)];
|
|
891
|
+
UIGestureRecognizer *guard = [self.pager valueForKey:@"verticalPagerGesture"];
|
|
892
|
+
XCTAssertEqual(guard.state, UIGestureRecognizerStatePossible);
|
|
893
|
+
for (NSInteger step = 1; step <= 8; ++step) {
|
|
894
|
+
[self.driver move:touch to:CGPointMake(point.x - 8, point.y - 12 * step)];
|
|
895
|
+
}
|
|
896
|
+
UIScrollView *vertical = [self.pager valueForKey:@"observedScrollView"];
|
|
897
|
+
UIScrollView *pager = [self.pager valueForKey:@"pagerScrollView"];
|
|
898
|
+
XCTAssertTrue(vertical.isDragging);
|
|
899
|
+
XCTAssertFalse(scroll.isDragging);
|
|
900
|
+
XCTAssertFalse(pager.isDragging);
|
|
901
|
+
XCTAssertEqual(self.longPressBegins, 0);
|
|
902
|
+
[self.driver end:touch];
|
|
903
|
+
XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 1);
|
|
904
|
+
XCTAssertEqual(pager.panGestureRecognizer.minimumNumberOfTouches, 1);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
- (void)testNestedHeldPanTouchCountRestoresOnSecondTouch
|
|
908
|
+
{
|
|
909
|
+
UIScrollView *scroll = [self mountNestedHorizontalScrollView];
|
|
910
|
+
CGPoint point = [self pressPointInNestedScrollView:scroll];
|
|
911
|
+
UITouch *first = [self.driver beginAt:point];
|
|
912
|
+
XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 2);
|
|
913
|
+
UITouch *second = [self.driver beginAt:CGPointMake(point.x + 20, point.y)];
|
|
914
|
+
UIScrollView *pager = [self.pager valueForKey:@"pagerScrollView"];
|
|
915
|
+
XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 1);
|
|
916
|
+
XCTAssertEqual(pager.panGestureRecognizer.minimumNumberOfTouches, 1);
|
|
917
|
+
[self.driver end:second];
|
|
918
|
+
[self.driver end:first];
|
|
919
|
+
XCTAssertEqual(scroll.panGestureRecognizer.minimumNumberOfTouches, 1);
|
|
920
|
+
}
|
|
921
|
+
|
|
812
922
|
@end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onekeyfe/react-native-pager-view",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.168",
|
|
4
4
|
"description": "React Native wrapper for Android and iOS ViewPager",
|
|
5
5
|
"source": "./src/index.tsx",
|
|
6
6
|
"main": "./lib/module/index.js",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"typescript": "^5.9.2"
|
|
73
73
|
},
|
|
74
74
|
"peerDependencies": {
|
|
75
|
-
"@onekeyfe/react-native-native-logger": "3.0.
|
|
75
|
+
"@onekeyfe/react-native-native-logger": "3.0.168",
|
|
76
76
|
"react": "*",
|
|
77
77
|
"react-native": "*"
|
|
78
78
|
},
|