React Native点击路由时重置动画进度条宽度的方法
解决方法
要实现每次进入路由时重置并重新播放进度条动画,核心是在路由聚焦时先将进度条宽度重置为0,再执行动画,同时用useRef持久化动画值避免重复创建。具体修改如下:
关键修改点
- 用
useRef保存Animated.Value,确保组件重新渲染时不会丢失当前动画状态 - 在
focus事件回调中,先调用setValue将宽度重置为0,再启动动画到目标宽度 - 完善监听的清理逻辑,避免内存泄漏
修改后的完整代码
import React, { useRef, useEffect } from 'react'; import { View, FlatList, StyleSheet, Dimensions, Animated } from 'react-native'; import { useIsFocused } from '@react-navigation/native'; const { width } = Dimensions.get("screen"); const SettingsScreen = ({navigation}) => { const isFocused = useIsFocused(); return ( <FlatList contentContainerStyle={style.barContainer} data={[1, 2, 3, 4, 5]} keyExtractor={(_, index) => index.toString()} renderItem={() => ( <ProgressBar navigation={navigation} /> )} ></FlatList> ); }; const ProgressBar = ({ navigation }) => { // 用useRef持久化动画值,避免每次渲染重新创建 const barWidth = useRef(new Animated.Value(0)).current; const finalWidth = width / 2; useEffect(() => { const listener = navigation.addListener("focus", () => { // 先重置宽度为初始值0 barWidth.setValue(0); // 再执行动画到目标宽度 Animated.spring(barWidth, { toValue: finalWidth, bounciness: 10, speed: 2, useNativeDriver: false, }).start(); }); // 组件卸载时移除监听 return () => listener(); }, [navigation, finalWidth]); return ( <View style={style.contentContainer}> <Animated.View style={[style.progressBar, { width: barWidth }]} /> </View> ); }; const style = StyleSheet.create({ contentContainer: { flex: 1, justifyContent: "center", padding: 30, }, barContainer: { padding: 30, }, progressBar: { backgroundColor: "green", width: width / 2, height: 15, borderRadius: 15, }, }); export default SettingsScreen;
原方案无效的原因
- 直接创建
new Animated.Value(0):每次组件渲染都会生成新的动画值,但路由聚焦时旧的动画值可能已经处于目标状态,新的动画值未及时触发动画 - 未执行重置操作:之前的代码仅执行从当前值到目标值的动画,若当前值已等于目标值,动画不会再次触发
内容的提问来源于stack exchange,提问作者fakermaker
相关产品推荐
相关产品推荐

