Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Animated.Flatlist and Animated.ScrollView to animate an Animated.View is not smooth

I am would like to make an animated header.

  1. I Created an animated component of FlatList,
  2. Used the onScroll function to update the animated value.
  3. Placed a view (Animated.View) as the header above the animated FlatList using position absolute.
  4. Finally, interpolate the animated value to change the view (Animated.View) using transform properties.

The animation works fine, but the animation is not smooth at all.

I saw this issue of how using scrollEventThrottle helps the smoothness. So I thought using FlatList would be smooth but it's not. If your scroll while pressing, it's smooth. But if you scroll and leave the finger, it's jumpy ( I don't know how to describe it. Sorry). The scrolling is smooth but the animated view (Header) animation is not smooth at all.

Environment

  • react: 16.0.0-alpha.12,
  • react-native: ^0.47.0,
  • node: v7.7.3
  • npm: 4.1.2
  • yarn: 0.21.3

Target Platform: iOS and Android

Build tools: expo

Link to snack demo

export default class AnimatedHeader extends React.Component {
	state = {
		animatedValue: new Animated.Value(0),
	};
	
	_renderItem = ({item}) => {
		return (
			<View style={styles.nonsenseItem}>
				<Text style={styles.itemText}>{item}</Text>
			</View>
		)
	};
	
	render() {
		let scaleY = this.state.animatedValue.interpolate({
			inputRange: [0, 180],
			outputRange: [1, 0.5],
			extrapolate: 'clamp',
		});
		
		let translateY = this.state.animatedValue.interpolate({
			inputRange: [0, 180],
			outputRange: [0, -100],
			extrapolate: 'clamp',
		});
		
		return (
			<View style={styles.container}>
				<AnimatedFlatList
					contentContainerStyle={{marginTop: 200}}
					scrollEventThrottle={16} // <-- Use 1 here to make sure no events are ever missed
					onScroll={Animated.event(
						[{nativeEvent: {contentOffset: {y: this.state.animatedValue}}}],
						{useNativeDriver: true} // <-- Add this
					)}
					data={data}
					renderItem={this._renderItem}
					keyExtractor={(item, i) => i}/>
				<Animated.View style={[styles.headerWrapper, {transform: [{scaleY}, {translateY}]}]}/>
			</View>
		)
	}
}

Update

So, I tried to implement the same functionality using ScrollView. However, I think, its event worse using ScrollView when compared to FlatList.

Here is the expo snack demo: Animated ScrollView Header

I think I need to mention how I got here at the first place. So, I tried to implement this by a very nice tutorial in Medium, and also by watching this awesome youtube react conf viedo by Brent. However, the exact code used on youtube video has the same effect. Also, on the Medium tutorial, the author has given a Link to his expo Animated header link, which works very smoothly. But the same code doesn't work smoothly when I copy paste the code. So, I think the problem is with the react or react native version. I will update if I have any new update. Thank you.

like image 983
Kakar Avatar asked Sep 03 '17 10:09

Kakar


People also ask

Which is better FlatList or ScrollView?

As opposed to the ScrollView, the FlatList renders only those elements that are currently being displayed on the screen (default: 10 items). Thus, it does not have any impact on the performance of the application. So, it is preferable to use the FlatList Component to display a large list of data.

What is the difference between FlatList and ScrollView?

ScrollView renders all its react child components at once, but this has a performance downside. FlatList renders items lazily, when they are about to appear, and removes items that scroll way off-screen to save memory and processing time.

How do you handle animation in RN?

Working with animations​Animations are started by calling start() on your animation. start() takes a completion callback that will be called when the animation is done.


1 Answers

There has been a regression in React Native 0.46 which, fortunately, has been fixed in 0.48.2 (see this issue and this PR). That's why you're having the issue with recent Expo versions. I've had this problem with custom parallax images, and this was solved by building a custom binary with RN 0.48.3.

Your code is fine, even though I would recommend setting scrollEventThrottle to 1 as this really helps smoothing things out on iOS.

like image 112
bend Avatar answered Oct 21 '22 06:10

bend