Today i want to make a progress bar with a image on the left. Unfortunately I can't position the image in the right place. For now it looks like that
I want to looks something like that -
My code so far -
<View
style={{
flexDirection: "row",
alignSelf: "center",
marginBottom: "20%",
marginTop: "10%",
}}
>
<View
style={{
width: "90%",
height: 30,
padding: 2.5,
backgroundColor: "#00000020",
borderRadius: 30,
}}
>
{/* <Animated.View
style={[
{
width: "100%",
height: 25,
borderRadius: 15,
backgroundColor: "#f5de41",
},
{
width: progressAnim,
},
]}
></Animated.View> */}
<Image
source={require("./assets/lion.png")}
style={{
height: 44,
height: 44,
position: "absolute",
}}
resizeMode="contain"
/>
</View>
</View>
I tried to add left: '-62%'
in style of iamge but it not works. I am not sure how to move the lion to the left?
CodePudding user response:
One approach would be to remove the absolute position and use flexbox to align the the image to end of the row:
const ProgressBar = ({imgSource,imgStyle,imgSize,style,progress,color})=>{
let loadingAnim = useRef(new Animated.Value(progress)).current;
const [{width,height},setViewDimensions] = useState({});
// get parent view size
const onLayout=({nativeEvent})=>{
setViewDimensions({
width:nativeEvent.layout.width,
height:nativeEvent.layout.height
})
}
const animatedWidth =loadingAnim.interpolate({
inputRange:[0,1],
outputRange:[0,width-imgSize],
extrapolate:'clamp'
})
const containerAnimation = {
margin:0,
padding:0,
width:Animated.add(animatedWidth,imgSize),
backgroundColor:color,
height:'100%',
justifyContent:'center',
overflow:'hidden'
}
useEffect(()=>{
Animated.timing(loadingAnim,{
toValue:progress,
duration:100
}).start()
},[progress])
return(
<View style={[styles.loadingContainer,{height:imgSize*1.5||null},style]} onLayout={onLayout}>
<Animated.View style={[styles.loadingContainer,containerAnimation]}>
<Animated.Image
source={imgSource}
style={[{height:imgSize,width:imgSize,alignSelf:'flex-end'},imgStyle,{}]}
/>
</Animated.View>
</View>
)
}
I found this approach to be slightly un-smooth. I think this is because the width of image's parent view was being animated, and not the actual position of the image.
Another approach would be to animate the image:
const ProgressBar = ({imgSource,imgStyle,imgSize,style,progress,color})=>{
let widthAnim = useRef(new Animated.Value(progress)).current;
const [{width,height},setViewDimensions] = useState({});
// get parent view width to determine progress view size
const onLayout=({nativeEvent})=>{
setViewDimensions({
width:nativeEvent.layout.width,
height:nativeEvent.layout.height
})
}
const animatedWidth = widthAnim.interpolate({
inputRange:[0,1],
outputRange:[0,width-imgSize],
extrapolate:'clamp'
})
const containerAnimation = {
// min width will be imgSize
width:Animated.add(animatedWidth,imgSize),
backgroundColor:color,
}
const imgAnimation = {
left:animatedWidth
}
// animate progress changess
useEffect(()=>{
Animated.timing(widthAnim,{
toValue:progress,
duration:100
}).start()
},[progress])
return(
<View>
<View style={[styles.loadingContainer,{height:imgSize*1.25||null},style]} onLayout={onLayout}>
<Animated.View style={[styles.progressBar,containerAnimation]}/>
</View>
<Animated.Image
source={imgSource}
style={[styles.image,{height:imgSize,width:imgSize},imgStyle,imgAnimation]}
resizeMode='contain'
/>
</View>
)
}