@lodev09/react-native-true-sheet 3.11.0-beta.11 → 3.11.0-beta.13
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.
- package/android/src/main/java/com/lodev09/truesheet/TrueSheetViewController.kt +28 -13
- package/android/src/main/java/com/lodev09/truesheet/core/TrueSheetCoordinatorLayout.kt +36 -1
- package/ios/TrueSheetContainerView.mm +17 -0
- package/ios/TrueSheetFooterView.mm +19 -0
- package/ios/TrueSheetView.mm +3 -0
- package/ios/TrueSheetViewController.h +2 -0
- package/ios/TrueSheetViewController.mm +27 -0
- package/package.json +1 -1
|
@@ -192,6 +192,11 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
192
192
|
private val jsTouchDispatcher = JSTouchDispatcher(this)
|
|
193
193
|
private val jsPointerDispatcher = JSPointerDispatcher(this)
|
|
194
194
|
|
|
195
|
+
// True when the active touch stream began inside the footer. Latched on
|
|
196
|
+
// ACTION_DOWN so subsequent MOVE events keep routing to the footer even if
|
|
197
|
+
// the finger drifts outside the footer's rect mid-gesture.
|
|
198
|
+
private var footerOwnsTouchStream = false
|
|
199
|
+
|
|
195
200
|
private val eventDispatcher
|
|
196
201
|
get() = delegate?.eventDispatcher
|
|
197
202
|
|
|
@@ -1291,26 +1296,36 @@ class TrueSheetViewController(private val reactContext: ThemedReactContext) :
|
|
|
1291
1296
|
|
|
1292
1297
|
override fun dispatchTouchEvent(event: MotionEvent): Boolean {
|
|
1293
1298
|
val footer = containerView?.footerView
|
|
1299
|
+
val action = event.actionMasked
|
|
1300
|
+
|
|
1294
1301
|
if (footer != null && footer.isShown) {
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1302
|
+
if (action == MotionEvent.ACTION_DOWN) {
|
|
1303
|
+
val loc = ScreenUtils.getScreenLocation(footer)
|
|
1304
|
+
val x = event.rawX.toInt()
|
|
1305
|
+
val y = event.rawY.toInt()
|
|
1306
|
+
footerOwnsTouchStream = x >= loc[0] &&
|
|
1307
|
+
x <= loc[0] + footer.width &&
|
|
1308
|
+
y >= loc[1] &&
|
|
1309
|
+
y <= loc[1] + footer.height
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
if (footerOwnsTouchStream) {
|
|
1313
|
+
val loc = ScreenUtils.getScreenLocation(footer)
|
|
1304
1314
|
val localEvent = MotionEvent.obtain(event)
|
|
1305
|
-
localEvent.setLocation(
|
|
1306
|
-
(touchX - footerLocation[0]).toFloat(),
|
|
1307
|
-
(touchY - footerLocation[1]).toFloat()
|
|
1308
|
-
)
|
|
1315
|
+
localEvent.setLocation(event.rawX - loc[0], event.rawY - loc[1])
|
|
1309
1316
|
val handled = footer.dispatchTouchEvent(localEvent)
|
|
1310
1317
|
localEvent.recycle()
|
|
1318
|
+
|
|
1319
|
+
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
|
1320
|
+
footerOwnsTouchStream = false
|
|
1321
|
+
}
|
|
1311
1322
|
if (handled) return true
|
|
1312
1323
|
}
|
|
1313
1324
|
}
|
|
1325
|
+
|
|
1326
|
+
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
|
1327
|
+
footerOwnsTouchStream = false
|
|
1328
|
+
}
|
|
1314
1329
|
return super.dispatchTouchEvent(event)
|
|
1315
1330
|
}
|
|
1316
1331
|
|
|
@@ -36,6 +36,14 @@ class TrueSheetCoordinatorLayout(context: Context) :
|
|
|
36
36
|
private var initialY = 0f
|
|
37
37
|
private var activePointerId = 0
|
|
38
38
|
|
|
39
|
+
// Horizontal-dominance tracking. iOS lets horizontal child gestures win over
|
|
40
|
+
// the sheet's vertical pan; we mirror that by locking out BottomSheetBehavior
|
|
41
|
+
// interception once the first significant movement of a stream is horizontal.
|
|
42
|
+
private var streamInitialX = 0f
|
|
43
|
+
private var streamInitialY = 0f
|
|
44
|
+
private var streamHorizontalLocked = false
|
|
45
|
+
private var streamDirectionDecided = false
|
|
46
|
+
|
|
39
47
|
init {
|
|
40
48
|
layoutParams = LayoutParams(
|
|
41
49
|
LayoutParams.MATCH_PARENT,
|
|
@@ -94,8 +102,35 @@ class TrueSheetCoordinatorLayout(context: Context) :
|
|
|
94
102
|
* See: https://github.com/facebook/react-native/pull/44099
|
|
95
103
|
*/
|
|
96
104
|
override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
|
|
97
|
-
|
|
105
|
+
val action = ev.actionMasked
|
|
106
|
+
|
|
107
|
+
if (action == MotionEvent.ACTION_DOWN) {
|
|
98
108
|
clearStaleNestedScrollingChildRef()
|
|
109
|
+
|
|
110
|
+
streamInitialX = ev.rawX
|
|
111
|
+
streamInitialY = ev.rawY
|
|
112
|
+
streamHorizontalLocked = false
|
|
113
|
+
streamDirectionDecided = false
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Decide gesture direction on first significant movement of the stream.
|
|
117
|
+
// If horizontal wins, lock out BottomSheetBehavior for the rest of the stream
|
|
118
|
+
// so child handlers (carousels, swipe buttons, etc.) can claim the touch.
|
|
119
|
+
if (!streamDirectionDecided && action == MotionEvent.ACTION_MOVE) {
|
|
120
|
+
val dx = kotlin.math.abs(ev.rawX - streamInitialX)
|
|
121
|
+
val dy = kotlin.math.abs(ev.rawY - streamInitialY)
|
|
122
|
+
if (dx > touchSlop || dy > touchSlop) {
|
|
123
|
+
streamDirectionDecided = true
|
|
124
|
+
streamHorizontalLocked = dx > dy
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (streamHorizontalLocked) {
|
|
129
|
+
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_CANCEL) {
|
|
130
|
+
streamHorizontalLocked = false
|
|
131
|
+
streamDirectionDecided = false
|
|
132
|
+
}
|
|
133
|
+
return false
|
|
99
134
|
}
|
|
100
135
|
|
|
101
136
|
val scrollView = delegate?.findScrollView()
|
|
@@ -72,10 +72,27 @@ using namespace facebook::react;
|
|
|
72
72
|
_headerView = nil;
|
|
73
73
|
_footerView = nil;
|
|
74
74
|
_scrollableSet = NO;
|
|
75
|
+
self.isAccessibilityElement = NO;
|
|
75
76
|
}
|
|
76
77
|
return self;
|
|
77
78
|
}
|
|
78
79
|
|
|
80
|
+
#pragma mark - Accessibility
|
|
81
|
+
|
|
82
|
+
- (NSArray *)accessibilityElements {
|
|
83
|
+
NSMutableArray *elements = [NSMutableArray array];
|
|
84
|
+
if (_headerView) {
|
|
85
|
+
[elements addObject:_headerView];
|
|
86
|
+
}
|
|
87
|
+
if (_contentView) {
|
|
88
|
+
[elements addObject:_contentView];
|
|
89
|
+
}
|
|
90
|
+
if (_footerView) {
|
|
91
|
+
[elements addObject:_footerView];
|
|
92
|
+
}
|
|
93
|
+
return elements;
|
|
94
|
+
}
|
|
95
|
+
|
|
79
96
|
#pragma mark - Layout
|
|
80
97
|
|
|
81
98
|
- (void)layoutSubviews {
|
|
@@ -37,6 +37,7 @@ using namespace facebook::react;
|
|
|
37
37
|
_props = defaultProps;
|
|
38
38
|
|
|
39
39
|
self.backgroundColor = [UIColor clearColor];
|
|
40
|
+
self.isAccessibilityElement = NO;
|
|
40
41
|
|
|
41
42
|
_lastHeight = 0;
|
|
42
43
|
_pendingHeight = 0;
|
|
@@ -47,6 +48,24 @@ using namespace facebook::react;
|
|
|
47
48
|
return self;
|
|
48
49
|
}
|
|
49
50
|
|
|
51
|
+
#pragma mark - Accessibility
|
|
52
|
+
|
|
53
|
+
- (NSArray *)accessibilityElements {
|
|
54
|
+
NSMutableArray *elements = [NSMutableArray array];
|
|
55
|
+
[self collectAccessibilityElementsFromView:self into:elements];
|
|
56
|
+
return elements;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
- (void)collectAccessibilityElementsFromView:(UIView *)view into:(NSMutableArray *)elements {
|
|
60
|
+
for (UIView *subview in view.subviews) {
|
|
61
|
+
if (subview.isAccessibilityElement || subview.accessibilityLabel || subview.accessibilityIdentifier) {
|
|
62
|
+
[elements addObject:subview];
|
|
63
|
+
} else {
|
|
64
|
+
[self collectAccessibilityElementsFromView:subview into:elements];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
50
69
|
#pragma mark - Layout
|
|
51
70
|
|
|
52
71
|
- (void)setupConstraintsWithHeight:(CGFloat)height {
|
package/ios/TrueSheetView.mm
CHANGED
|
@@ -373,6 +373,9 @@ using namespace facebook::react;
|
|
|
373
373
|
[_controller.view addSubview:_containerView];
|
|
374
374
|
[LayoutUtil pinView:_containerView toParentView:_controller.view edges:UIRectEdgeAll];
|
|
375
375
|
[_controller.view bringSubviewToFront:_containerView];
|
|
376
|
+
_containerView.accessibilityViewIsModal = YES;
|
|
377
|
+
_controller.accessibilityContentView = _containerView;
|
|
378
|
+
[_controller setupAccessibilityContainer];
|
|
376
379
|
|
|
377
380
|
CGFloat contentHeight = [_containerView contentHeight];
|
|
378
381
|
if (contentHeight > 0) {
|
|
@@ -75,9 +75,11 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
75
75
|
@property (nonatomic, assign) BOOL isPresented;
|
|
76
76
|
@property (nonatomic, assign) NSInteger activeDetentIndex;
|
|
77
77
|
@property (nonatomic, readonly) BOOL isTopmostPresentedController;
|
|
78
|
+
@property (nonatomic, weak, nullable) UIView *accessibilityContentView;
|
|
78
79
|
|
|
79
80
|
@property (nonatomic, readonly) CGFloat screenHeight;
|
|
80
81
|
|
|
82
|
+
- (void)setupAccessibilityContainer;
|
|
81
83
|
- (void)applyActiveDetent;
|
|
82
84
|
- (void)setupActiveDetentWithIndex:(NSInteger)index;
|
|
83
85
|
- (void)resizeToDetentIndex:(NSInteger)index;
|
|
@@ -34,6 +34,8 @@ static BOOL TrueSheetPositionStateEquals(TrueSheetPositionState a, TrueSheetPosi
|
|
|
34
34
|
|
|
35
35
|
@interface TrueSheetViewController ()
|
|
36
36
|
|
|
37
|
+
- (void)setAccessibilityContentElement:(UIView *)contentView;
|
|
38
|
+
|
|
37
39
|
@end
|
|
38
40
|
|
|
39
41
|
@implementation TrueSheetViewController {
|
|
@@ -207,6 +209,7 @@ static BOOL TrueSheetPositionStateEquals(TrueSheetPositionState a, TrueSheetPosi
|
|
|
207
209
|
if ([presenter isKindOfClass:[TrueSheetViewController class]]) {
|
|
208
210
|
_parentSheetController = (TrueSheetViewController *)presenter;
|
|
209
211
|
[_parentSheetController.delegate viewControllerWillBlur];
|
|
212
|
+
[_parentSheetController setAccessibilityContentElement:self.accessibilityContentView ?: self.view];
|
|
210
213
|
}
|
|
211
214
|
|
|
212
215
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
@@ -241,10 +244,33 @@ static BOOL TrueSheetPositionStateEquals(TrueSheetPositionState a, TrueSheetPosi
|
|
|
241
244
|
});
|
|
242
245
|
|
|
243
246
|
[self setupGestureRecognizer];
|
|
247
|
+
[self setupAccessibilityContainer];
|
|
244
248
|
_isPresented = YES;
|
|
245
249
|
}
|
|
246
250
|
}
|
|
247
251
|
|
|
252
|
+
- (void)setupAccessibilityContainer {
|
|
253
|
+
UIView *contentView = self.accessibilityContentView;
|
|
254
|
+
if (!contentView) {
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
[self setAccessibilityContentElement:contentView];
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
- (void)setAccessibilityContentElement:(UIView *)contentView {
|
|
262
|
+
self.view.isAccessibilityElement = NO;
|
|
263
|
+
self.view.accessibilityViewIsModal = YES;
|
|
264
|
+
self.view.accessibilityElements = @[ contentView ];
|
|
265
|
+
|
|
266
|
+
UIView *presentedView = self.presentationController.presentedView;
|
|
267
|
+
if (presentedView) {
|
|
268
|
+
presentedView.isAccessibilityElement = NO;
|
|
269
|
+
presentedView.accessibilityViewIsModal = YES;
|
|
270
|
+
presentedView.accessibilityElements = @[ contentView ];
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
|
|
248
274
|
- (void)emitWillDismissEvents {
|
|
249
275
|
if (self.isBeingDismissed && !_isWillDismissEmitted) {
|
|
250
276
|
_isWillDismissEmitted = YES;
|
|
@@ -264,6 +290,7 @@ static BOOL TrueSheetPositionStateEquals(TrueSheetPositionState a, TrueSheetPosi
|
|
|
264
290
|
_anchorView = nil;
|
|
265
291
|
|
|
266
292
|
[_parentSheetController.delegate viewControllerDidFocus];
|
|
293
|
+
[_parentSheetController setupAccessibilityContainer];
|
|
267
294
|
_parentSheetController = nil;
|
|
268
295
|
|
|
269
296
|
[self.delegate viewControllerDidBlur];
|
package/package.json
CHANGED