如何在React Native中基于API数据展示自定义配送进度条?已尝试step-indicators模块但不符合需求
Hey there! I get it—off-the-shelf modules like step-indicators don’t always fit the exact design you need, especially for delivery progress tracking tied to real API data. Let’s build a custom, flexible progress bar that you can tailor to your UI and data structure.
Core Approach
- First, fetch delivery step data from your API (each step should include a name, status like
completed/active/pending, and unique ID) - Use React Native's basic
Viewcomponents to build step nodes and connecting lines, dynamically updating styles based on each step's status - Map directly to your API data structure so the progress bar automatically updates when your backend data changes
Full Implementation Code
First, let's assume your API returns data in this structure:
// Sample API response data const deliveryStepsFromAPI = [ { id: 1, title: "Order Confirmed", status: "completed" }, { id: 2, title: "Shipped from Warehouse", status: "completed" }, { id: 3, title: "Out for Delivery", status: "active" }, { id: 4, title: "Delivered", status: "pending" } ];
Now build the custom progress bar component:
import React from 'react'; import { View, Text, StyleSheet } from 'react-native'; const DeliveryProgressBar = ({ steps }) => { // Get dynamic styles for step nodes based on status const getNodeStyle = (status) => { switch(status) { case 'completed': return { backgroundColor: '#27ae60', borderColor: '#27ae60' }; case 'active': return { backgroundColor: '#3498db', borderColor: '#3498db' }; default: return { backgroundColor: '#e0e0e0', borderColor: '#bdbdbd' }; } }; // Get dynamic styles for connecting lines const getLineStyle = (index) => { if (index === 0) return {}; // No line before the first step const previousStep = steps[index - 1]; if (previousStep.status === 'completed' || previousStep.status === 'active') { return { backgroundColor: '#27ae60' }; } return { backgroundColor: '#bdbdbd' }; }; return ( <View style={styles.progressContainer}> {steps.map((step, index) => ( <View key={step.id} style={styles.stepWrapper}> {/* Connecting line (hidden for first step) */} {index !== 0 && ( <View style={[styles.connectingLine, getLineStyle(index)]} /> )} {/* Step node */} <View style={[styles.stepNode, getNodeStyle(step.status)]}> {step.status === 'completed' && <Text style={styles.nodeIcon}>✓</Text>} {step.status === 'active' && <Text style={styles.nodeIcon}>•</Text>} {step.status === 'pending' && <Text style={styles.nodeIcon}>{index + 1}</Text>} </View> {/* Step title */} <Text style={[styles.stepTitle, step.status !== 'pending' && styles.activeTitle]}> {step.title} </Text> </View> ))} </View> ); }; const styles = StyleSheet.create({ progressContainer: { flexDirection: 'row', alignItems: 'center', paddingVertical: 20, paddingHorizontal: 12, backgroundColor: '#ffffff', borderRadius: 10, marginHorizontal: 16, shadowColor: '#000', shadowOffset: { width: 0, height: 2 }, shadowOpacity: 0.1, shadowRadius: 4 }, stepWrapper: { flex: 1, alignItems: 'center', position: 'relative' }, connectingLine: { position: 'absolute', left: -50, top: 12, width: 100, height: 2 }, stepNode: { width: 26, height: 26, borderRadius: 13, borderWidth: 2, justifyContent: 'center', alignItems: 'center', marginBottom: 6 }, nodeIcon: { color: '#ffffff', fontSize: 12, fontWeight: '600' }, stepTitle: { fontSize: 11, color: '#757575', textAlign: 'center' }, activeTitle: { color: '#27ae60', fontWeight: '500' } }); export default DeliveryProgressBar;
How to Use the Component
In your screen, fetch the API data and pass it to the progress bar:
import React, { useEffect, useState } from 'react'; import { View, StyleSheet, Text } from 'react-native'; import DeliveryProgressBar from './DeliveryProgressBar'; const DeliveryTrackingScreen = () => { const [deliverySteps, setDeliverySteps] = useState([]); const [isLoading, setIsLoading] = useState(true); useEffect(() => { // Replace with your actual API call const fetchDeliveryData = async () => { try { const response = await fetch('https://your-api-endpoint.com/delivery-steps'); const data = await response.json(); setDeliverySteps(data); } catch (error) { console.error('Failed to fetch delivery data:', error); } finally { setIsLoading(false); } }; fetchDeliveryData(); }, []); return ( <View style={styles.screenContainer}> {isLoading ? ( <Text style={styles.loadingText}>Loading delivery progress...</Text> ) : ( <DeliveryProgressBar steps={deliverySteps} /> )} </View> ); }; const styles = StyleSheet.create({ screenContainer: { flex: 1, justifyContent: 'center', backgroundColor: '#f5f5f5' }, loadingText: { textAlign: 'center', fontSize: 14, color: '#616161' } }); export default DeliveryTrackingScreen;
Customization Tips
- Style Tweaks: Adjust colors, node sizes, border widths, or shadows in the
stylesobject to match your design exactly - Extra Statuses: Add more cases to
getNodeStyleandgetLineStyleif your API returns additional statuses (likedelayedorfailed) - Animations: Use React Native's
Animatedmodule to add smooth transitions when statuses change (e.g., fade in completed nodes) - Scrollable Layout: If you have more than 4 steps, add
overflow: 'scroll'to theprogressContainerstyle to make it horizontally scrollable
内容的提问来源于stack exchange,提问作者Pratap Penmetsa
相关产品推荐
相关产品推荐

