Skip to content

Commit

Permalink
native animated scroll event support
Browse files Browse the repository at this point in the history
Reviewed By: yungsters

Differential Revision: D4648383

fbshipit-source-id: fdb8e2deaa06b2d2f9002cee2c0b827dbd7a5570
  • Loading branch information
sahrens authored and facebook-github-bot committed Mar 10, 2017
1 parent 28ed5ed commit 5177a55
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 6 deletions.
42 changes: 37 additions & 5 deletions Examples/UIExplorer/js/FlatListExample.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
const React = require('react');
const ReactNative = require('react-native');
const {
Animated,
FlatList,
StyleSheet,
View,
Expand All @@ -47,6 +48,8 @@ const {
renderSmallSwitchOption,
} = require('./ListExampleShared');

const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);

const VIEWABILITY_CONFIG = {
minimumViewTime: 3000,
viewAreaCoveragePercentThreshold: 100,
Expand All @@ -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) => (
Expand All @@ -95,7 +112,6 @@ class FlatListExample extends React.PureComponent {
<PlainInput
onChangeText={this._onChangeScrollToIndex}
placeholder="scrollToIndex..."
style={styles.searchTextInput}
/>
</View>
<View style={styles.options}>
Expand All @@ -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}
Expand All @@ -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}
Expand Down Expand Up @@ -180,7 +206,7 @@ class FlatListExample extends React.PureComponent {
}
};
_pressItem = (key: number) => {
this._listRef.recordInteraction();
this._listRef.getNode().recordInteraction();
pressItem(this, key);
};
_listRef: FlatList<*>;
Expand All @@ -196,6 +222,12 @@ const styles = StyleSheet.create({
searchRow: {
paddingHorizontal: 10,
},
spindicator: {
marginLeft: 'auto',
width: 2,
height: 16,
backgroundColor: 'darkgray',
},
});

module.exports = FlatListExample;
9 changes: 9 additions & 0 deletions Libraries/CustomComponents/Lists/FlatList.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');

Expand Down Expand Up @@ -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);
}
Expand Down
12 changes: 11 additions & 1 deletion Libraries/CustomComponents/Lists/VirtualizedList.js
Original file line number Diff line number Diff line change
Expand Up @@ -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');
Expand Down Expand Up @@ -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],
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit 5177a55

Please sign in to comment.