7
7
* of patent rights can be found in the PATENTS file in the same directory.
8
8
*
9
9
* @providesModule ScrollView
10
- * @flow
11
10
*/
12
11
'use strict' ;
13
12
@@ -25,6 +24,7 @@ const {
25
24
requireNativeComponent,
26
25
} = ReactNative ;
27
26
27
+ const createReactClass = require ( 'create-react-class' ) ;
28
28
const PropTypes = require ( 'prop-types' ) ;
29
29
const ColorPropType = require ( 'react-native/Libraries/StyleSheet/ColorPropType' ) ;
30
30
const ScrollResponder = require ( 'react-native/Libraries/Components/ScrollResponder' ) ;
@@ -36,6 +36,9 @@ const ViewStylePropTypes = require('react-native/Libraries/Components/View/ViewS
36
36
const dismissKeyboard = require ( 'react-native/Libraries/Utilities/dismissKeyboard' ) ;
37
37
const invariant = require ( 'fbjs/lib/invariant' ) ;
38
38
const processDecelerationRate = require ( 'react-native/Libraries/Components/ScrollView/processDecelerationRate' ) ;
39
+ const warning = require ( 'fbjs/lib/warning' ) ;
40
+
41
+ import type { NativeMethodsMixinType } from 'ReactNativeTypes' ;
39
42
40
43
/**
41
44
* Forked from https://github.com/facebook/react-native/blob/0.45-stable/Libraries/Components/ScrollView/ScrollView.js
@@ -75,7 +78,8 @@ const processDecelerationRate = require('react-native/Libraries/Components/Scrol
75
78
* supports out of the box.
76
79
*/
77
80
// $FlowFixMe(>=0.41.0)
78
- const ScrollView = React . createClass ( {
81
+ const ScrollView = createReactClass ( {
82
+ displayName : 'ScrollView' ,
79
83
propTypes : {
80
84
...ViewPropTypes ,
81
85
/**
@@ -138,16 +142,18 @@ const ScrollView = React.createClass({
138
142
* These styles will be applied to the scroll view content container which
139
143
* wraps all of the child views. Example:
140
144
*
141
- * return (
142
- * <ScrollView contentContainerStyle={styles.contentContainer}>
143
- * </ScrollView>
144
- * );
145
- * ...
146
- * const styles = StyleSheet.create({
147
- * contentContainer: {
148
- * paddingVertical: 20
149
- * }
150
- * });
145
+ * ```
146
+ * return (
147
+ * <ScrollView contentContainerStyle={styles.contentContainer}>
148
+ * </ScrollView>
149
+ * );
150
+ * ...
151
+ * const styles = StyleSheet.create({
152
+ * contentContainer: {
153
+ * paddingVertical: 20
154
+ * }
155
+ * });
156
+ * ```
151
157
*/
152
158
contentContainerStyle : StyleSheetPropType ( ViewStylePropTypes ) ,
153
159
/**
@@ -156,8 +162,10 @@ const ScrollView = React.createClass({
156
162
* shortcuts `"normal"` and `"fast"` which match the underlying iOS settings
157
163
* for `UIScrollViewDecelerationRateNormal` and
158
164
* `UIScrollViewDecelerationRateFast` respectively.
159
- * - normal: 0.998 (the default)
160
- * - fast: 0.99
165
+ *
166
+ * - `'normal'`: 0.998 (the default)
167
+ * - `'fast'`: 0.99
168
+ *
161
169
* @platform ios
162
170
*/
163
171
decelerationRate : PropTypes . oneOfType ( [
@@ -171,9 +179,11 @@ const ScrollView = React.createClass({
171
179
horizontal : PropTypes . bool ,
172
180
/**
173
181
* The style of the scroll indicators.
174
- * - `default` (the default), same as `black`.
175
- * - `black`, scroll indicator is black. This style is good against a light background.
176
- * - `white`, scroll indicator is white. This style is good against a dark background.
182
+ *
183
+ * - `'default'` (the default), same as `black`.
184
+ * - `'black'`, scroll indicator is black. This style is good against a light background.
185
+ * - `'white'`, scroll indicator is white. This style is good against a dark background.
186
+ *
177
187
* @platform ios
178
188
*/
179
189
indicatorStyle : PropTypes . oneOf ( [
@@ -195,9 +205,10 @@ const ScrollView = React.createClass({
195
205
canCancelContentTouches : PropTypes . bool ,
196
206
/**
197
207
* Determines whether the keyboard gets dismissed in response to a drag.
198
- * - 'none' (the default), drags do not dismiss the keyboard.
199
- * - 'on-drag', the keyboard is dismissed when a drag begins.
200
- * - 'interactive', the keyboard is dismissed interactively with the drag and moves in
208
+ *
209
+ * - `'none'` (the default), drags do not dismiss the keyboard.
210
+ * - `'on-drag'`, the keyboard is dismissed when a drag begins.
211
+ * - `'interactive'`, the keyboard is dismissed interactively with the drag and moves in
201
212
* synchrony with the touch; dragging upwards cancels the dismissal.
202
213
* On android this is not supported and it will have the same behavior as 'none'.
203
214
*/
@@ -209,14 +220,14 @@ const ScrollView = React.createClass({
209
220
/**
210
221
* Determines when the keyboard should stay visible after a tap.
211
222
*
212
- * - ' never' (the default), tapping outside of the focused text input when the keyboard
223
+ * - ` never` (the default), tapping outside of the focused text input when the keyboard
213
224
* is up dismisses the keyboard. When this happens, children won't receive the tap.
214
- * - ' always' , the keyboard will not dismiss automatically, and the scroll view will not
225
+ * - ` always` , the keyboard will not dismiss automatically, and the scroll view will not
215
226
* catch taps, but children of the scroll view can catch taps.
216
- * - ' handled' , the keyboard will not dismiss automatically when the tap was handled by
227
+ * - ` handled` , the keyboard will not dismiss automatically when the tap was handled by
217
228
* a children, (or captured by an ancestor).
218
- * - false, deprecated, use 'never' instead
219
- * - true, deprecated, use 'always' instead
229
+ * - ` false` , deprecated, use 'never' instead
230
+ * - ` true` , deprecated, use 'always' instead
220
231
*/
221
232
keyboardShouldPersistTaps : PropTypes . oneOf ( [ 'always' , 'never' , 'handled' , false , true ] ) ,
222
233
/**
@@ -256,7 +267,7 @@ const ScrollView = React.createClass({
256
267
*/
257
268
pagingEnabled : PropTypes . bool ,
258
269
/**
259
- * When false, the content does not scroll.
270
+ * When false, the view cannot be scrolled via touch interaction
260
271
* The default value is true.
261
272
*/
262
273
scrollEnabled : PropTypes . bool ,
@@ -308,17 +319,21 @@ const ScrollView = React.createClass({
308
319
/**
309
320
* When set, causes the scroll view to stop at multiples of the value of
310
321
* `snapToInterval`. This can be used for paginating through children
311
- * that have lengths smaller than the scroll view. Used in combination
312
- * with `snapToAlignment`.
322
+ * that have lengths smaller than the scroll view. Typically used in
323
+ * combination with `snapToAlignment` and `decelerationRate="fast"`.
324
+ * Overrides less configurable `pagingEnabled` prop.
325
+ *
313
326
* @platform ios
314
327
*/
315
328
snapToInterval : PropTypes . number ,
316
329
/**
317
330
* When `snapToInterval` is set, `snapToAlignment` will define the relationship
318
331
* of the snapping to the scroll view.
319
- * - `start` (the default) will align the snap at the left (horizontal) or top (vertical)
320
- * - `center` will align the snap in the center
321
- * - `end` will align the snap at the right (horizontal) or bottom (vertical)
332
+ *
333
+ * - `'start'` (the default) will align the snap at the left (horizontal) or top (vertical)
334
+ * - `'center'` will align the snap in the center
335
+ * - `'end'` will align the snap at the right (horizontal) or bottom (vertical)
336
+ *
322
337
* @platform ios
323
338
*/
324
339
snapToAlignment : PropTypes . oneOf ( [
@@ -383,6 +398,15 @@ const ScrollView = React.createClass({
383
398
'always' ,
384
399
'never' ,
385
400
] ) ,
401
+ /**
402
+ * When true, ScrollView will emit updateChildFrames data in scroll events,
403
+ * otherwise will not compute or emit child frame data. This only exists
404
+ * to support legacy issues, `onLayout` should be used instead to retrieve
405
+ * frame data.
406
+ * The default value is false.
407
+ * @platform ios
408
+ */
409
+ DEPRECATED_sendUpdatedChildFrames : PropTypes . bool
386
410
} ,
387
411
388
412
mixins : [ ScrollResponder . Mixin ] ,
@@ -490,24 +514,30 @@ const ScrollView = React.createClass({
490
514
this . scrollTo ( { x, y, animated : false } ) ;
491
515
} ,
492
516
517
+ /**
518
+ * Displays the scroll indicators momentarily.
519
+ *
520
+ * @platform ios
521
+ */
522
+ flashScrollIndicators : function ( ) {
523
+ this . getScrollResponder ( ) . scrollResponderFlashScrollIndicators ( ) ;
524
+ } ,
525
+
493
526
_getKeyForIndex : function ( index , childArray ) {
494
527
const child = childArray [ index ] ;
495
528
return child && child . key ;
496
529
} ,
497
530
498
531
_updateAnimatedNodeAttachment : function ( ) {
532
+ if ( this . _scrollAnimatedValueAttachment ) {
533
+ this . _scrollAnimatedValueAttachment . detach ( ) ;
534
+ }
499
535
if ( this . props . stickyHeaderIndices && this . props . stickyHeaderIndices . length > 0 ) {
500
- if ( ! this . _scrollAnimatedValueAttachment ) {
501
- this . _scrollAnimatedValueAttachment = Animated . attachNativeEvent (
502
- this . _scrollViewRef ,
503
- 'onScroll' ,
504
- [ { nativeEvent : { contentOffset : { y : this . _scrollAnimatedValue } } } ]
505
- ) ;
506
- }
507
- } else {
508
- if ( this . _scrollAnimatedValueAttachment ) {
509
- this . _scrollAnimatedValueAttachment . detach ( ) ;
510
- }
536
+ this . _scrollAnimatedValueAttachment = Animated . attachNativeEvent (
537
+ this . _scrollViewRef ,
538
+ 'onScroll' ,
539
+ [ { nativeEvent : { contentOffset : { y : this . _scrollAnimatedValue } } } ]
540
+ ) ;
511
541
}
512
542
} ,
513
543
@@ -572,8 +602,8 @@ const ScrollView = React.createClass({
572
602
this . _scrollViewRef = ref ;
573
603
} ,
574
604
575
- _innerViewRef : ( null : ?View ) ,
576
- _setInnerViewRef : function ( ref : ?View ) {
605
+ _innerViewRef : ( null : ?NativeMethodsMixinType ) ,
606
+ _setInnerViewRef : function ( ref : ?NativeMethodsMixinType ) {
577
607
this . _innerViewRef = ref ;
578
608
} ,
579
609
@@ -583,6 +613,10 @@ const ScrollView = React.createClass({
583
613
if ( Platform . OS === 'ios' ) {
584
614
ScrollViewClass = RCTScrollView ;
585
615
ScrollContentContainerViewClass = RCTScrollContentView ;
616
+ warning (
617
+ ! this . props . snapToInterval || ! this . props . pagingEnabled ,
618
+ 'snapToInterval is currently ignored when pagingEnabled is true.'
619
+ ) ;
586
620
} else if ( Platform . OS === 'android' ) {
587
621
if ( this . props . horizontal ) {
588
622
ScrollViewClass = AndroidHorizontalScrollView ;
@@ -656,7 +690,13 @@ const ScrollView = React.createClass({
656
690
{ ...contentSizeChangeProps }
657
691
ref = { this . _setInnerViewRef}
658
692
style = { contentContainerStyle}
659
- removeClippedSubviews = { this. props . removeClippedSubviews }
693
+ removeClippedSubviews = {
694
+ // Subview clipping causes issues with sticky headers on Android and
695
+ // would be hard to fix properly in a performant way.
696
+ Platform. OS === 'android' && hasStickyHeaders ?
697
+ false :
698
+ this . props . removeClippedSubviews
699
+ }
660
700
collapsable = { false } >
661
701
{ children}
662
702
< / S c r o l l C o n t e n t C o n t a i n e r V i e w C l a s s > ;
@@ -671,6 +711,10 @@ const ScrollView = React.createClass({
671
711
this . props . alwaysBounceVertical :
672
712
! this . props . horizontal ;
673
713
714
+
715
+ const DEPRECATED_sendUpdatedChildFrames =
716
+ ! ! this . props . DEPRECATED_sendUpdatedChildFrames ;
717
+
674
718
const baseStyle = this . props . horizontal ? styles . baseHorizontal : styles . baseVertical ;
675
719
const props = {
676
720
...this . props ,
@@ -699,6 +743,7 @@ const ScrollView = React.createClass({
699
743
scrollEventThrottle : hasStickyHeaders ? 1 : this . props . scrollEventThrottle ,
700
744
sendMomentumEvents : ( this . props . onMomentumScrollBegin || this . props . onMomentumScrollEnd ) ?
701
745
true : false ,
746
+ DEPRECATED_sendUpdatedChildFrames
702
747
} ;
703
748
704
749
const { decelerationRate } = this . props ;
@@ -795,6 +840,7 @@ if (Platform.OS === 'android') {
795
840
( ScrollView : ReactClass < any > ) ,
796
841
nativeOnlyProps ,
797
842
) ;
843
+ // $FlowFixMe (bvaughn) Update ComponentInterface in ViewPropTypes to include a string type (for Fiber host components) in a follow-up.
798
844
RCTScrollContentView = requireNativeComponent ( 'RCTScrollContentView' , View ) ;
799
845
}
800
846
0 commit comments