我是 React Native 新手,正在尝试创建以下屏幕:
我尝试使用两种方法:
import React, { useState, useEffect } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import Svg, { Circle, Text as SvgText } from 'react-native-svg';
interface ProgressCircleProps {
radius: number;
strokeWidth: number;
progress: number; // Should be a value between 0 and 1
color: string;
}
const ProgressCircle: React.FC<ProgressCircleProps> = ({
radius,
strokeWidth,
progress,
color,
}) => {
const [circumference, setCircumference] = useState(0);
useEffect(() => {
const circumferenceValue = 2 * Math.PI * radius;
setCircumference(circumferenceValue);
}, [radius]);
const strokeDashoffset = circumference * (1 - progress);
const progressPercentage = `${Math.round(progress * 100)}%`;
return (
<View style={{ aspectRatio: 1, width: radius * 2 }}>
<Svg width={radius * 2} height={radius * 2}>
<Circle
stroke={color}
fill="transparent"
strokeWidth={strokeWidth}
strokeDasharray={circumference}
strokeDashoffset={strokeDashoffset}
cx={radius}
cy={radius}
r={radius - strokeWidth / 2}
/>
<SvgText
x="50%"
y="50%"
textAnchor="middle"
alignmentBaseline="middle"
fontSize={radius / 2.5}
fill="#333" // Adjust text color as needed
fontWeight="bold"
>
{progressPercentage}
</SvgText>
</Svg>
</View>
);
};
export default ProgressCircle;
和
import React, { useState, useEffect } from 'react';
import { View } from 'react-native';
import Svg, { Circle } from 'react-native-svg';
interface ProgressCircleProps {
radius: number;
strokeWidth: number;
progress: number; // Should be a value between 0 and 1
color: string;
}
const ProgressCircle: React.FC<ProgressCircleProps> = ({
radius,
strokeWidth,
progress,
color,
}) => {
const [circumference, setCircumference] = useState(0);
useEffect(() => {
const circumferenceValue = 2 * Math.PI * radius;
setCircumference(circumferenceValue);
}, [radius]);
const strokeDashoffset = circumference * (1 - progress);
return (
<View style={{ aspectRatio: 1, width: radius * 2 }}>
<Svg width={radius * 2} height={radius * 2}>
<Circle
stroke={color}
fill="transparent"
strokeWidth={strokeWidth}
strokeDasharray={`${circumference} ${circumference}`}
strokeDashoffset={strokeDashoffset}
cx={radius}
cy={radius}
r={radius - strokeWidth / 2}
/>
</Svg>
</View>
);
};
export default ProgressCircle;
在这两种情况下都会重叠
CircularProgressBar
,将其完全隐藏。
有什么建议吗?
确保您的项目中已安装
react-native-svg
。
npm install react-native-svg
然后尝试运行以下代码,该代码基于您上面的示例
import React, { useState, useEffect } from 'react';
import { View, StyleSheet, Text } from 'react-native';
import Svg, { Circle, Text as SvgText } from 'react-native-svg';
interface ProgressCircleProps {
radius: number;
strokeWidth: number;
progress: number; // Should be a value between 0 and 1
color: string;
}
const ProgressCircle: React.FC<ProgressCircleProps> = ({
radius,
strokeWidth,
progress,
color,
}) => {
const [circumference, setCircumference] = useState(0);
useEffect(() => {
const circumferenceValue = 2 * Math.PI * radius;
setCircumference(circumferenceValue);
}, [radius]);
const strokeDashoffset = circumference * (1 - progress);
const progressValue = Math.round(progress * 2000); // Assuming progress is between 0 and 1 and total is 2000
return (
<View style={{ aspectRatio: 1, width: radius * 2 }}>
<Svg width={radius * 2} height={radius * 2}>
<Circle
stroke={color}
fill="transparent"
strokeWidth={strokeWidth}
strokeDasharray={circumference}
strokeDashoffset={strokeDashoffset}
cx={radius}
cy={radius}
r={radius - strokeWidth / 2}
/>
<SvgText
x="50%"
y="50%"
textAnchor="middle"
alignmentBaseline="middle"
fontSize={radius / 2.5}
fill={color}
fontWeight="bold"
>
{progressValue}
</SvgText>
</Svg>
</View>
);
};
export default ProgressCircle;
// Usage example
const App = () => {
const [progress, setProgress] = useState(0.96); // Example progress value (1923/2000)
return (
<View style={styles.container}>
<Text style={styles.header}>2000 contatos</Text>
<ProgressCircle
radius={100}
strokeWidth={10}
progress={progress}
color="blue"
/>
<View style={styles.button}>
<Text style={styles.buttonText}>⟳</Text>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
header: {
fontSize: 20,
fontWeight: 'bold',
marginBottom: 20,
},
button: {
marginTop: 40,
padding: 10,
backgroundColor: 'blue',
borderRadius: 5,
},
buttonText: {
color: 'white',
fontSize: 20,
textAlign: 'center',
},
});
export default App;