native animated scroll event support
Reviewed By: yungsters Differential Revision: D4648383 fbshipit-source-id: fdb8e2deaa06b2d2f9002cee2c0b827dbd7a5570
This commit is contained in:
parent
28ed5eddf2
commit
5177a55314
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue