我猜如果你想要在React Native中动画改变视图的话,可能没有直接的方法。不过,在你的情况下,我可以想到一个小技巧,使用 opacity
、position: absolute
和 interpolate()
的组合。以下是一个最小化示例,你可以直接复制粘贴测试:
import React, { Component } from 'react';
import { StyleSheet, Animated, View, ScrollView } from 'react-native';
class AnimationExample extends Component {
constructor(props) {
super(props)
this.state = {
showBlueView: false,
animatedOpacityValue: new Animated.Value(0),
}
}
handleScroll = (event) => {
const { animatedOpacityValue, showBlueView } = this.state;
const scrollPosition = event.nativeEvent.contentOffset.y;
if (scrollPosition > 100 && !showBlueView) {
Animated.timing(animatedOpacityValue, {
toValue: 1,
}).start(() => this.setState({ showBlueView: true }))
}
if (scrollPosition < 100 && showBlueView) {
Animated.timing(animatedOpacityValue, {
toValue: 0,
}).start(() => this.setState({ showBlueView: false }))
}
}
render() {
const { animatedOpacityValue } = this.state;
return (
<ScrollView
style={styles.scrollView}
onScroll={this.handleScroll}
scrollEventThrottle={16}
>
<View style={styles.green} />
<View style={styles.animatedViewsPositioner}>
<Animated.View
style={{
...styles.red,
opacity: animatedOpacityValue.interpolate({
inputRange: [0, 1],
outputRange: [1, 0],
}),
}}
/>
<Animated.View
style={{
...styles.blue,
opacity: animatedOpacityValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
}),
}}
/>
</View>
</ScrollView>
)
}
}
const styles = StyleSheet.create({
scrollView: {
flex: 1,
},
green: {
height: 600,
width: '100%',
backgroundColor: 'green',
},
red: {
height: 300,
width: '100%',
backgroundColor: 'red',
},
blue: {
position: 'absolute',
height: 300,
width: '100%',
backgroundColor: 'blue',
},
animatedViewsPositioner: {
position: 'relative',
},
})
在上面的例子中,我首先通过将
handleScroll
函数应用于
scrollView
来访问滚动位置。确保将
scrollEventThrottle
设置为16,以确保每秒触发一次该函数,但要注意可能由此引起的性能问题(如果您关心,可以查看
这里了解更多信息)。
为了在用户滚动到特定位置时触发视图更改(实际上并不是这样,但看起来像),我使用一个
view
来包装红色和蓝色视图,红色视图默认为
opacity:1
,而蓝色视图默认为
opacity:0
,位于红色视图之上。
我通过使用
interpolate()
来使它们的
opacity
动画化来隐藏红色视图并显示蓝色视图。在帮助下,两个不透明度值都由放置在状态中的一个animatedValue
animatedOpacityValue
控制。我添加了一个状态
showBlueView
来通过避免由onScroll触发的不断设置状态来优化性能。
这里有一个更新,可以在两个视图上添加
touchableOpacities
,只需在未使用蓝色视图时隐藏它即可。
首先,添加一个日志功能:
log = (stringToPrint) => () => {
console.log(stringToPrint)
}
接下来,通过添加两个
TouchableOpacity
,将
scrollView
更改为以下形式
<ScrollView
style={styles.scrollView}
onScroll={this.handleScroll}
scrollEventThrottle={16}
>
<View style={styles.green} />
<View style={styles.animatedViewsPositioner}>
<Animated.View
style={{
...styles.red,
opacity: animatedOpacityValue.interpolate({
inputRange: [0, 1],
outputRange: [1, 0],
}),
}}
>
<TouchableOpacity
style={{ backgroundColor: 'black', width: 80, height: 30 }}
onPress={this.log('click on red')}
/>
</Animated.View>
{showBlueView && (
<Animated.View
style={{
...styles.blue,
opacity: animatedOpacityValue.interpolate({
inputRange: [0, 1],
outputRange: [0, 1],
}),
}}
>
<TouchableOpacity
style={{ backgroundColor: 'black', width: 80, height: 30 }}
onPress={this.log('click on blue')}
/>
</Animated.View>
)}
</View>
</ScrollView>
请注意,我添加了
showBlueView &&
以在不透明度为0时隐藏蓝色视图,这样它就不会阻止应用于红色视图的任何点击事件(即使蓝色视图被隐藏,它实际上位于具有
opacity: 0
的红色视图之上)。
view1
放进一个scrollView
中,当滚动到特定位置时将view1
更换为view2
吗? - Andus