Skip to content

Commit 7693044

Browse files
Rebase from react-native@0.47.1
1 parent 0b4635d commit 7693044

File tree

4 files changed

+117
-56
lines changed

4 files changed

+117
-56
lines changed

android/src/main/java/com/rnnestedscrollview/RNNestedScrollViewPackage.java

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ public List<NativeModule> createNativeModules(ReactApplicationContext reactConte
1616
return Collections.emptyList();
1717
}
1818

19-
@Override
20-
public List<Class<? extends JavaScriptModule>> createJSModules() {
21-
return Collections.emptyList();
22-
}
23-
2419
@Override
2520
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
2621
return Arrays.<ViewManager>asList(

android/src/main/java/com/rnnestedscrollview/ReactNestedScrollView.java

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
import com.facebook.react.common.ReactConstants;
3333
import com.facebook.react.views.scroll.FpsListener;
3434
import com.facebook.react.views.scroll.OnScrollDispatchHelper;
35+
import com.facebook.react.views.scroll.VelocityHelper;
3536
import com.facebook.react.uimanager.MeasureSpecAssertions;
3637
import com.facebook.react.uimanager.events.NativeGestureUtil;
3738
import com.facebook.react.uimanager.ReactClippingViewGroup;
@@ -55,6 +56,7 @@ public class ReactNestedScrollView extends NestedScrollView implements ReactClip
5556

5657
private final OnScrollDispatchHelper mOnScrollDispatchHelper = new OnScrollDispatchHelper();
5758
private final OverScroller mScroller;
59+
private final VelocityHelper mVelocityHelper = new VelocityHelper();
5860

5961
private @Nullable Rect mClippingRect;
6062
private boolean mDoneFlinging;
@@ -171,7 +173,10 @@ protected void onScrollChanged(int x, int y, int oldX, int oldY) {
171173
mDoneFlinging = false;
172174
}
173175

174-
ReactNestedScrollViewHelper.emitScrollEvent(this);
176+
ReactNestedScrollViewHelper.emitScrollEvent(
177+
this,
178+
mOnScrollDispatchHelper.getXFlingVelocity(),
179+
mOnScrollDispatchHelper.getYFlingVelocity());
175180
}
176181
}
177182

@@ -198,12 +203,17 @@ public boolean onTouchEvent(MotionEvent ev) {
198203
return false;
199204
}
200205

206+
mVelocityHelper.calculateVelocity(ev);
201207
int action = ev.getAction() & MotionEvent.ACTION_MASK;
202208
if (action == MotionEvent.ACTION_UP && mDragging) {
203-
ReactNestedScrollViewHelper.emitScrollEndDragEvent(this);
209+
ReactNestedScrollViewHelper.emitScrollEndDragEvent(
210+
this,
211+
mVelocityHelper.getXVelocity(),
212+
mVelocityHelper.getYVelocity());
204213
mDragging = false;
205214
disableFpsListener();
206215
}
216+
207217
return super.onTouchEvent(ev);
208218
}
209219

android/src/main/java/com/rnnestedscrollview/ReactNestedScrollViewHelper.java

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,16 @@ public class ReactNestedScrollViewHelper {
3232
/**
3333
* Shared by {@link ReactNestedScrollView} and {@link ReactHorizontalScrollView}.
3434
*/
35-
public static void emitScrollEvent(ViewGroup scrollView) {
36-
emitScrollEvent(scrollView, ScrollEventType.SCROLL);
35+
public static void emitScrollEvent(ViewGroup scrollView, float xVelocity, float yVelocity) {
36+
emitScrollEvent(scrollView, ScrollEventType.SCROLL, xVelocity, yVelocity);
3737
}
3838

3939
public static void emitScrollBeginDragEvent(ViewGroup scrollView) {
4040
emitScrollEvent(scrollView, ScrollEventType.BEGIN_DRAG);
4141
}
4242

43-
public static void emitScrollEndDragEvent(ViewGroup scrollView) {
44-
emitScrollEvent(scrollView, ScrollEventType.END_DRAG);
43+
public static void emitScrollEndDragEvent(ViewGroup scrollView, float xVelocity, float yVelocity) {
44+
emitScrollEvent(scrollView, ScrollEventType.END_DRAG, xVelocity, yVelocity);
4545
}
4646

4747
public static void emitScrollMomentumBeginEvent(ViewGroup scrollView) {
@@ -53,6 +53,14 @@ public static void emitScrollMomentumEndEvent(ViewGroup scrollView) {
5353
}
5454

5555
private static void emitScrollEvent(ViewGroup scrollView, ScrollEventType scrollEventType) {
56+
emitScrollEvent(scrollView, scrollEventType, 0, 0);
57+
}
58+
59+
private static void emitScrollEvent(
60+
ViewGroup scrollView,
61+
ScrollEventType scrollEventType,
62+
float xVelocity,
63+
float yVelocity) {
5664
View contentView = scrollView.getChildAt(0);
5765

5866
if (contentView == null) {
@@ -66,6 +74,8 @@ private static void emitScrollEvent(ViewGroup scrollView, ScrollEventType scroll
6674
scrollEventType,
6775
scrollView.getScrollX(),
6876
scrollView.getScrollY(),
77+
xVelocity,
78+
yVelocity,
6979
contentView.getWidth(),
7080
contentView.getHeight(),
7181
scrollView.getWidth(),

lib/NestedScrollView.js

Lines changed: 91 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
* of patent rights can be found in the PATENTS file in the same directory.
88
*
99
* @providesModule ScrollView
10-
* @flow
1110
*/
1211
'use strict';
1312

@@ -25,6 +24,7 @@ const {
2524
requireNativeComponent,
2625
} = ReactNative;
2726

27+
const createReactClass = require('create-react-class');
2828
const PropTypes = require('prop-types');
2929
const ColorPropType = require('react-native/Libraries/StyleSheet/ColorPropType');
3030
const ScrollResponder = require('react-native/Libraries/Components/ScrollResponder');
@@ -36,6 +36,9 @@ const ViewStylePropTypes = require('react-native/Libraries/Components/View/ViewS
3636
const dismissKeyboard = require('react-native/Libraries/Utilities/dismissKeyboard');
3737
const invariant = require('fbjs/lib/invariant');
3838
const processDecelerationRate = require('react-native/Libraries/Components/ScrollView/processDecelerationRate');
39+
const warning = require('fbjs/lib/warning');
40+
41+
import type {NativeMethodsMixinType} from 'ReactNativeTypes';
3942

4043
/**
4144
* 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
7578
* supports out of the box.
7679
*/
7780
// $FlowFixMe(>=0.41.0)
78-
const ScrollView = React.createClass({
81+
const ScrollView = createReactClass({
82+
displayName: 'ScrollView',
7983
propTypes: {
8084
...ViewPropTypes,
8185
/**
@@ -138,16 +142,18 @@ const ScrollView = React.createClass({
138142
* These styles will be applied to the scroll view content container which
139143
* wraps all of the child views. Example:
140144
*
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+
* ```
151157
*/
152158
contentContainerStyle: StyleSheetPropType(ViewStylePropTypes),
153159
/**
@@ -156,8 +162,10 @@ const ScrollView = React.createClass({
156162
* shortcuts `"normal"` and `"fast"` which match the underlying iOS settings
157163
* for `UIScrollViewDecelerationRateNormal` and
158164
* `UIScrollViewDecelerationRateFast` respectively.
159-
* - normal: 0.998 (the default)
160-
* - fast: 0.99
165+
*
166+
* - `'normal'`: 0.998 (the default)
167+
* - `'fast'`: 0.99
168+
*
161169
* @platform ios
162170
*/
163171
decelerationRate: PropTypes.oneOfType([
@@ -171,9 +179,11 @@ const ScrollView = React.createClass({
171179
horizontal: PropTypes.bool,
172180
/**
173181
* 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+
*
177187
* @platform ios
178188
*/
179189
indicatorStyle: PropTypes.oneOf([
@@ -195,9 +205,10 @@ const ScrollView = React.createClass({
195205
canCancelContentTouches: PropTypes.bool,
196206
/**
197207
* 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
201212
* synchrony with the touch; dragging upwards cancels the dismissal.
202213
* On android this is not supported and it will have the same behavior as 'none'.
203214
*/
@@ -209,14 +220,14 @@ const ScrollView = React.createClass({
209220
/**
210221
* Determines when the keyboard should stay visible after a tap.
211222
*
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
213224
* 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
215226
* 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
217228
* 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
220231
*/
221232
keyboardShouldPersistTaps: PropTypes.oneOf(['always', 'never', 'handled', false, true]),
222233
/**
@@ -256,7 +267,7 @@ const ScrollView = React.createClass({
256267
*/
257268
pagingEnabled: PropTypes.bool,
258269
/**
259-
* When false, the content does not scroll.
270+
* When false, the view cannot be scrolled via touch interaction
260271
* The default value is true.
261272
*/
262273
scrollEnabled: PropTypes.bool,
@@ -308,17 +319,21 @@ const ScrollView = React.createClass({
308319
/**
309320
* When set, causes the scroll view to stop at multiples of the value of
310321
* `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+
*
313326
* @platform ios
314327
*/
315328
snapToInterval: PropTypes.number,
316329
/**
317330
* When `snapToInterval` is set, `snapToAlignment` will define the relationship
318331
* 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+
*
322337
* @platform ios
323338
*/
324339
snapToAlignment: PropTypes.oneOf([
@@ -383,6 +398,15 @@ const ScrollView = React.createClass({
383398
'always',
384399
'never',
385400
]),
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
386410
},
387411

388412
mixins: [ScrollResponder.Mixin],
@@ -490,24 +514,30 @@ const ScrollView = React.createClass({
490514
this.scrollTo({x, y, animated: false});
491515
},
492516

517+
/**
518+
* Displays the scroll indicators momentarily.
519+
*
520+
* @platform ios
521+
*/
522+
flashScrollIndicators: function() {
523+
this.getScrollResponder().scrollResponderFlashScrollIndicators();
524+
},
525+
493526
_getKeyForIndex: function(index, childArray) {
494527
const child = childArray[index];
495528
return child && child.key;
496529
},
497530

498531
_updateAnimatedNodeAttachment: function() {
532+
if (this._scrollAnimatedValueAttachment) {
533+
this._scrollAnimatedValueAttachment.detach();
534+
}
499535
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+
);
511541
}
512542
},
513543

@@ -572,8 +602,8 @@ const ScrollView = React.createClass({
572602
this._scrollViewRef = ref;
573603
},
574604

575-
_innerViewRef: (null: ?View),
576-
_setInnerViewRef: function(ref: ?View) {
605+
_innerViewRef: (null: ?NativeMethodsMixinType),
606+
_setInnerViewRef: function(ref: ?NativeMethodsMixinType) {
577607
this._innerViewRef = ref;
578608
},
579609

@@ -583,6 +613,10 @@ const ScrollView = React.createClass({
583613
if (Platform.OS === 'ios') {
584614
ScrollViewClass = RCTScrollView;
585615
ScrollContentContainerViewClass = RCTScrollContentView;
616+
warning(
617+
!this.props.snapToInterval || !this.props.pagingEnabled,
618+
'snapToInterval is currently ignored when pagingEnabled is true.'
619+
);
586620
} else if (Platform.OS === 'android') {
587621
if (this.props.horizontal) {
588622
ScrollViewClass = AndroidHorizontalScrollView;
@@ -656,7 +690,13 @@ const ScrollView = React.createClass({
656690
{...contentSizeChangeProps}
657691
ref={this._setInnerViewRef}
658692
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+
}
660700
collapsable={false}>
661701
{children}
662702
</ScrollContentContainerViewClass>;
@@ -671,6 +711,10 @@ const ScrollView = React.createClass({
671711
this.props.alwaysBounceVertical :
672712
!this.props.horizontal;
673713

714+
715+
const DEPRECATED_sendUpdatedChildFrames =
716+
!!this.props.DEPRECATED_sendUpdatedChildFrames;
717+
674718
const baseStyle = this.props.horizontal ? styles.baseHorizontal : styles.baseVertical;
675719
const props = {
676720
...this.props,
@@ -699,6 +743,7 @@ const ScrollView = React.createClass({
699743
scrollEventThrottle: hasStickyHeaders ? 1 : this.props.scrollEventThrottle,
700744
sendMomentumEvents: (this.props.onMomentumScrollBegin || this.props.onMomentumScrollEnd) ?
701745
true : false,
746+
DEPRECATED_sendUpdatedChildFrames
702747
};
703748

704749
const { decelerationRate } = this.props;
@@ -795,6 +840,7 @@ if (Platform.OS === 'android') {
795840
(ScrollView: ReactClass<any>),
796841
nativeOnlyProps,
797842
);
843+
// $FlowFixMe (bvaughn) Update ComponentInterface in ViewPropTypes to include a string type (for Fiber host components) in a follow-up.
798844
RCTScrollContentView = requireNativeComponent('RCTScrollContentView', View);
799845
}
800846

0 commit comments

Comments
 (0)