React Native Expo自定义进度条:基于总步数的宽度计算数学实现
React Native Expo 自定义进度条:宽度计算与动画实现
一、宽度计算的核心公式
要让进度条宽度随步骤按比例变化,核心逻辑是:当前进度宽度 = (当前步骤 / 总步数) × 进度条容器的总宽度
这个公式的优势:
- 适配不同尺寸的进度条容器,不需要硬写固定增量(比如你原来的
50) - 进度始终和步骤占比严格对应,总步数变化时也能自动适配
二、代码修复与动画实现
你的现有代码存在useEffect缺少依赖项、普通state无法实现动画等问题,下面是修正后的完整代码:
import React, { useState, useEffect, useRef } from 'react'; import { View, Text, Animated } from 'react-native'; const ProgressBar = ({ step, request }) => { const [steps, setSteps] = useState(0); const [accessToken, setAccessToken] = useState(null); const [containerWidth, setContainerWidth] = useState(0); // 用Animated.Value管理宽度,实现动画效果 const animatedWidth = useRef(new Animated.Value(0)).current; // 获取token useEffect(() => { const getToken = async () => { const token = await token.get(); setAccessToken(token); }; getToken(); }, []); // 根据token和request更新总步数 useEffect(() => { if (accessToken) { setSteps(request === 1 ? 6 : 7); } else { setSteps(3); } }, [accessToken, request]); // 获取进度条容器的总宽度 const handleContainerLayout = (e) => { const width = e.nativeEvent.layout.width; setContainerWidth(width); // 初始化宽度动画 Animated.timing(animatedWidth, { toValue: (step / steps) * width, duration: 300, useNativeDriver: false, }).start(); }; // 当step或steps变化时,更新进度条宽度(带动画) useEffect(() => { if (containerWidth === 0) return; Animated.timing(animatedWidth, { toValue: (step / steps) * containerWidth, duration: 300, // 可根据需求调整动画时长 useNativeDriver: false, }).start(); }, [step, steps, containerWidth]); return ( <View style={{ flexDirection: 'row', alignItems: 'center' }}> <View style={styles.progressBar} onLayout={handleContainerLayout}> <Animated.View style={[styles.progress, { width: animatedWidth }]} /> </View> <Text style={styles.progressText}>{step}/{steps}</Text> </View> ); }; // 示例样式,可按需调整 const styles = { progressBar: { height: 8, borderRadius: 4, backgroundColor: '#e0e0e0', marginRight: 10, flex: 1, }, progress: { height: '100%', borderRadius: 4, backgroundColor: '#2196F3', }, progressText: { fontSize: 14, color: '#666', }, }; export default ProgressBar;
关键修改说明:
- 改用
Animated.Value和Animated.timing实现平滑的宽度变化动画 - 单独存储进度条容器宽度作为计算基准值
- 给每个useEffect添加正确的依赖项,避免无效渲染
- 拆分总步数更新逻辑,代码结构更清晰
内容的提问来源于stack exchange,提问作者Wafa Tu
相关产品推荐
相关产品推荐

