in src/native-common/ScrollView.tsx [45:141]
render() {
let scrollThrottle = this.props.scrollEventThrottle || 16;
if (scrollThrottle === 0) {
// Fire at 60fps
scrollThrottle = 16;
}
const layoutCallback = this.props.onLayout ?
// We have a callback function, call the wrapper
this._onLayout :
undefined;
let scrollHandler;
if (this.props.scrollXAnimatedValue || this.props.scrollYAnimatedValue) {
// For more details on this craziness, reference:
// https://facebook.github.io/react-native/docs/animated#handling-gestures-and-other-events
const handlerWrapper: RN.EventMapping = {
nativeEvent: {
contentOffset: { },
},
};
if (this.props.scrollXAnimatedValue) {
handlerWrapper.nativeEvent.contentOffset.x = this.props.scrollXAnimatedValue;
}
if (this.props.scrollYAnimatedValue) {
handlerWrapper.nativeEvent.contentOffset.y = this.props.scrollYAnimatedValue;
}
const eventConfig: RN.AnimatedEventConfig<RN.NativeScrollEvent> = {
useNativeDriver: true,
};
if (this.props.onScroll) {
eventConfig.listener = this._onScroll;
}
// react-native.d.ts is wrong for the eventconfig typing, so casting to any for now.
scrollHandler = RN.Animated.event([handlerWrapper], eventConfig as any);
} else if (this.props.onScroll) {
scrollHandler = this._onScroll;
} else {
scrollHandler = undefined;
}
// 1) keyboardShouldPersistTaps may be overridden, superceding all other settings
// 2) in the absence of any other setting, 'never' is the default
// 3) if a boolean is seen, translate to 'always' or 'never' as the boolean is deprecated
// 4) it is also possible to see a string value of 'handled'
let keyboardShouldPersistTaps: ScrollViewProps['keyboardShouldPersistTaps'] = 'never';
if (overrideKeyboardShouldPersistTaps || this.props.keyboardShouldPersistTaps === true) {
// If there is an override or a boolean true, translate it to 'always'
keyboardShouldPersistTaps = 'always';
} else if (typeof this.props.keyboardShouldPersistTaps === 'string') {
// If there is no override, and a string && non-boolean was provided, use it without translation
keyboardShouldPersistTaps = this.props.keyboardShouldPersistTaps;
}
// NOTE: We are setting `automaticallyAdjustContentInsets` to false
// (http://facebook.github.io/react-native/docs/scrollview.html#automaticallyadjustcontentinsets). The
// 'automaticallyAdjustContentInsets' property is designed to offset the ScrollView's content to account for the
// navigation and tab bars in iOS.
// (navigationBarHidden={true}). We believe that React Native may not be calculating the content insets for the
// ScrollView correctly in this situation. Disabling this calculation seems to fix the ScrollView inset issues.
// Currently RX does not expose any components that would require `automaticallyAdjustContentInsets` to be
// set to true.
// We also set removeClippedSubviews to false, overriding the default value. Most of the scroll views
// we use are virtualized anyway.
const internalProps: RN.ScrollViewProps & React.Props<RN.ScrollView> = {
ref: this._setNativeComponent,
// Bug in react-native.d.ts. style should be "style?: StyleProp<ScrollViewStyle>;" but instead is ViewStyle.
style: this.props.style as any,
onScroll: scrollHandler,
automaticallyAdjustContentInsets: false,
showsHorizontalScrollIndicator: this.props.showsHorizontalScrollIndicator,
showsVerticalScrollIndicator: this.props.showsVerticalScrollIndicator,
keyboardDismissMode: this.props.keyboardDismissMode,
keyboardShouldPersistTaps: keyboardShouldPersistTaps,
scrollEnabled: this.props.scrollEnabled,
onContentSizeChange: this.props.onContentSizeChange,
onLayout: layoutCallback,
scrollEventThrottle: scrollThrottle,
horizontal: this.props.horizontal,
bounces: this.props.bounces,
pagingEnabled: this.props.pagingEnabled,
snapToInterval: this.props.snapToInterval,
decelerationRate: typeof this.props.snapToInterval === 'number' ? 'fast' : undefined,
scrollsToTop: this.props.scrollsToTop,
removeClippedSubviews: false,
overScrollMode: this.props.overScrollMode,
scrollIndicatorInsets: this.props.scrollIndicatorInsets,
onScrollBeginDrag: this.props.onScrollBeginDrag,
onScrollEndDrag: this.props.onScrollEndDrag,
children: this.props.children,
testID: this.props.testId,
};
return this._render(internalProps);
}