native animated scroll event support

Reviewed By: yungsters

Differential Revision: D4648383

fbshipit-source-id: fdb8e2deaa06b2d2f9002cee2c0b827dbd7a5570
This commit is contained in:
Spencer Ahrens 2017-03-09 22:01:15 -08:00 committed by Facebook Github Bot
parent 28ed5eddf2
commit 5177a55314
3 changed files with 57 additions and 6 deletions

View File

@ -26,6 +26,7 @@
const React = require('react');
const ReactNative = require('react-native');
const {
Animated,
FlatList,
StyleSheet,
View,
@ -47,6 +48,8 @@ const {
renderSmallSwitchOption,
} = require('./ListExampleShared');
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
const VIEWABILITY_CONFIG = {
minimumViewTime: 3000,
viewAreaCoveragePercentThreshold: 100,
@ -66,15 +69,29 @@ class FlatListExample extends React.PureComponent {
logViewable: false,
virtualized: true,
};
_onChangeFilterText = (filterText) => {
this.setState({filterText});
};
_onChangeScrollToIndex = (text) => {
this._listRef.scrollToIndex({viewPosition: 0.5, index: Number(text)});
this._listRef.getNode().scrollToIndex({viewPosition: 0.5, index: Number(text)});
};
_scrollPos = new Animated.Value(0);
_scrollSinkX = Animated.event(
[{nativeEvent: { contentOffset: { x: this._scrollPos } }}],
{useNativeDriver: true},
);
_scrollSinkY = Animated.event(
[{nativeEvent: { contentOffset: { y: this._scrollPos } }}],
{useNativeDriver: true},
);
componentDidUpdate() {
this._listRef.recordInteraction(); // e.g. flipping logViewable switch
this._listRef.getNode().recordInteraction(); // e.g. flipping logViewable switch
}
render() {
const filterRegex = new RegExp(String(this.state.filterText), 'i');
const filter = (item) => (
@ -95,7 +112,6 @@ class FlatListExample extends React.PureComponent {
<PlainInput
onChangeText={this._onChangeScrollToIndex}
placeholder="scrollToIndex..."
style={styles.searchTextInput}
/>
</View>
<View style={styles.options}>
@ -104,10 +120,19 @@ class FlatListExample extends React.PureComponent {
{renderSmallSwitchOption(this, 'fixedHeight')}
{renderSmallSwitchOption(this, 'logViewable')}
{renderSmallSwitchOption(this, 'debug')}
<Animated.View style={[styles.spindicator, {
transform: [
{rotate: this._scrollPos.interpolate({
inputRange: [0, 5000],
outputRange: ['0deg', '360deg'],
extrapolate: 'extend',
})}
]
}]} />
</View>
</View>
<SeparatorComponent />
<FlatList
<AnimatedFlatList
HeaderComponent={HeaderComponent}
FooterComponent={FooterComponent}
SeparatorComponent={SeparatorComponent}
@ -125,6 +150,7 @@ class FlatListExample extends React.PureComponent {
legacyImplementation={false}
numColumns={1}
onRefresh={this._onRefresh}
onScroll={this.state.horizontal ? this._scrollSinkX : this._scrollSinkY}
onViewableItemsChanged={this._onViewableItemsChanged}
ref={this._captureRef}
refreshing={false}
@ -180,7 +206,7 @@ class FlatListExample extends React.PureComponent {
}
};
_pressItem = (key: number) => {
this._listRef.recordInteraction();
this._listRef.getNode().recordInteraction();
pressItem(this, key);
};
_listRef: FlatList<*>;
@ -196,6 +222,12 @@ const styles = StyleSheet.create({
searchRow: {
paddingHorizontal: 10,
},
spindicator: {
marginLeft: 'auto',
width: 2,
height: 16,
backgroundColor: 'darkgray',
},
});
module.exports = FlatListExample;

View File

@ -34,6 +34,7 @@
const MetroListView = require('MetroListView'); // Used as a fallback legacy option
const React = require('React');
const ReactNative = require('ReactNative');
const View = require('View');
const VirtualizedList = require('VirtualizedList');
@ -235,6 +236,14 @@ class FlatList<ItemT> extends React.PureComponent<DefaultProps, Props<ItemT>, vo
this._listRef.recordInteraction();
}
getScrollableNode() {
if (this._listRef && this._listRef.getScrollableNode) {
return this._listRef.getScrollableNode();
} else {
return ReactNative.findNodeHandle(this._listRef);
}
}
componentWillMount() {
this._checkProps(this.props);
}

View File

@ -34,6 +34,7 @@
const Batchinator = require('Batchinator');
const React = require('React');
const ReactNative = require('ReactNative');
const RefreshControl = require('RefreshControl');
const ScrollView = require('ScrollView');
const View = require('View');
@ -237,6 +238,14 @@ class VirtualizedList extends React.PureComponent<OptionalProps, Props, State> {
this._updateViewableItems(this.props.data);
}
getScrollableNode() {
if (this._scrollRef && this._scrollRef.getScrollableNode) {
return this._scrollRef.getScrollableNode();
} else {
return ReactNative.findNodeHandle(this._scrollRef);
}
}
static defaultProps = {
disableVirtualization: false,
getItem: (data: any, index: number) => data[index],
@ -293,7 +302,8 @@ class VirtualizedList extends React.PureComponent<OptionalProps, Props, State> {
super(props);
invariant(
!props.onScroll || !props.onScroll.__isNative,
'VirtualizedList does not support AnimatedEvent with onScroll and useNativeDriver',
'Components based on VirtualizedList must be wrapped with Animated.createAnimatedComponent ' +
'to support native onScroll events with useNativeDriver',
);
this._updateCellsToRenderBatcher = new Batchinator(
this._updateCellsToRender,