[change] ScrollView event normalization

This commit is contained in:
Nicolas Gallagher
2016-12-12 14:21:33 +00:00
parent f8d5c15405
commit 4c46126ffe
3 changed files with 54 additions and 11 deletions
+15 -3
View File
@@ -38,6 +38,18 @@ which this `ScrollView` renders.
Fires at most once per frame during scrolling. The frequency of the events can Fires at most once per frame during scrolling. The frequency of the events can
be contolled using the `scrollEventThrottle` prop. be contolled using the `scrollEventThrottle` prop.
Invoked on scroll with the following event:
```js
{
nativeEvent: {
contentOffset: { x, y },
contentSize: { height, width },
layoutMeasurement: { height, width }
}
}
```
**refreshControl**: element **refreshControl**: element
TODO TODO
@@ -51,8 +63,8 @@ When false, the content does not scroll.
**scrollEventThrottle**: number = 0 **scrollEventThrottle**: number = 0
This controls how often the scroll event will be fired while scrolling (in This controls how often the scroll event will be fired while scrolling (as a
events per seconds). A higher number yields better accuracy for code that is time interval in ms). A lower number yields better accuracy for code that is
tracking the scroll position, but can lead to scroll performance problems. The tracking the scroll position, but can lead to scroll performance problems. The
default value is `0`, which means the scroll event will be sent only once each default value is `0`, which means the scroll event will be sent only once each
time the view is scrolled. time the view is scrolled.
@@ -104,7 +116,7 @@ export default class ScrollViewExample extends Component {
contentContainerStyle={styles.container} contentContainerStyle={styles.container}
horizontal horizontal
onScroll={(e) => this.onScroll(e)} onScroll={(e) => this.onScroll(e)}
scrollEventThrottle={60} scrollEventThrottle={100}
style={styles.root} style={styles.root}
/> />
) )
@@ -1,13 +1,15 @@
import React from 'react'; import React from 'react';
import { storiesOf, action } from '@kadira/storybook'; import { action, storiesOf } from '@kadira/storybook';
import { ScrollView, StyleSheet, Text, TouchableHighlight, View } from 'react-native' import { ScrollView, StyleSheet, Text, TouchableHighlight, View } from 'react-native'
const onScroll = action('ScrollView.onScroll');
storiesOf('component: ScrollView', module) storiesOf('component: ScrollView', module)
.add('vertical', () => ( .add('vertical', () => (
<View style={styles.scrollViewContainer}> <View style={styles.scrollViewContainer}>
<ScrollView <ScrollView
contentContainerStyle={styles.scrollViewContentContainerStyle} contentContainerStyle={styles.scrollViewContentContainerStyle}
onScroll={e => { console.log('ScrollView.onScroll', e); } } onScroll={onScroll}
scrollEventThrottle={1000} // 1 event per second scrollEventThrottle={1000} // 1 event per second
style={styles.scrollViewStyle} style={styles.scrollViewStyle}
> >
@@ -24,8 +26,8 @@ storiesOf('component: ScrollView', module)
<ScrollView <ScrollView
contentContainerStyle={styles.scrollViewContentContainerStyle} contentContainerStyle={styles.scrollViewContentContainerStyle}
horizontal horizontal
onScroll={e => console.log('ScrollView.onScroll', e)} onScroll={onScroll}
scrollEventThrottle={1} // 1 event per second scrollEventThrottle={16} // ~60 events per second
style={styles.scrollViewStyle} style={styles.scrollViewStyle}
> >
{Array.from({ length: 50 }).map((item, i) => ( {Array.from({ length: 50 }).map((item, i) => (
@@ -48,10 +50,10 @@ const styles = StyleSheet.create({
width: 300 width: 300
}, },
scrollViewStyle: { scrollViewStyle: {
borderWidth: '1px' borderWidth: 1
}, },
scrollViewContentContainerStyle: { scrollViewContentContainerStyle: {
backgroundColor: '#eee', backgroundColor: '#eee',
padding: '10px' padding: 10
} }
}) })
+31 -2
View File
@@ -10,6 +10,35 @@ import debounce from 'debounce';
import View from '../View'; import View from '../View';
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
const normalizeScrollEvent = (e) => ({
nativeEvent: {
contentOffset: {
get x() {
return e.target.scrollLeft;
},
get y() {
return e.target.scrollTop;
}
},
contentSize: {
get height() {
return e.target.scrollHeight;
},
get width() {
return e.target.scrollWidth;
}
},
layoutMeasurement: {
get height() {
return e.target.offsetHeight;
},
get width() {
return e.target.offsetWidth;
}
}
}
});
/** /**
* Encapsulates the Web-specific scroll throttling and disabling logic * Encapsulates the Web-specific scroll throttling and disabling logic
*/ */
@@ -75,13 +104,13 @@ export default class ScrollViewBase extends Component {
_handleScrollTick(e) { _handleScrollTick(e) {
const { onScroll } = this.props; const { onScroll } = this.props;
this._state.scrollLastTick = Date.now(); this._state.scrollLastTick = Date.now();
if (onScroll) { onScroll(e); } if (onScroll) { onScroll(normalizeScrollEvent(e)); }
} }
_handleScrollEnd(e) { _handleScrollEnd(e) {
const { onScroll } = this.props; const { onScroll } = this.props;
this._state.isScrolling = false; this._state.isScrolling = false;
if (onScroll) { onScroll(e); } if (onScroll) { onScroll(normalizeScrollEvent(e)); }
} }
_shouldEmitScrollEvent(lastTick, eventThrottle) { _shouldEmitScrollEvent(lastTick, eventThrottle) {