英文:
Animate a single card on an array that is mapping in React Native
问题
谢谢您的帖子。所以,我正在按照我的代码示例进行操作,但出于某种原因我的动画没有触发。useRef中的数组已经更改,但动画没有工作,对于可能出现的问题有什么想法,这是我的代码。我正在尝试在用户按下“查看信息”按钮时展开我的卡片,使其高度更高。谢谢!
const animateCardAll = useRef([]);
{markersArr.map((marker, index) => {
animateCardAll.current[index] = new Animated.Value(CARD_HEIGHT);
marker.isExpanded = false;
(marker.imageFetched = false), console.log(marker);
return (
<>
<Animated.View
key={marker._id}
style={[
styles.card,
{
height: animateCardAll.current[index],
},
]}
>
{marker.imageId ? (
<LazyImage
index={index}
imageId={marker.imageId}
userToken={userToken}
ref={(cardRefs.current[index] = marker)}
/>
) : null}
<View style={styles.textContent}>
<Text style={styles.cardTitle} numberOfLines={1}>
Address: {marker.address}
</Text>
<Text style={styles.cardDescription} numberOfLines={1}>
{marker.city}, {marker.zip_code} {marker.uSstate}
</Text>
{cardRefs.current[index] &&
cardRefs.current[index].isExpanded ? (
<ReviewsComponent
index={index}
addressId={marker._id}
userToken={userToken}
/>
) : null}
</View>
<View style={styles.button}>
<TouchableOpacity
onPress={() => {
expandCardAll(index);
}}
style={[
styles.signIn,
{
borderColor: "#398984",
borderWidth: 1,
},
]}
>
<Text
style={[
styles.textSign,
{
color: "#398984",
},
]}
>
VIEW INFORMATION
</Text>
</TouchableOpacity>
</View>
</Animated.View>
</>
);
})}
</Animated.ScrollView>
) : null}
const expandCardAll = (index) => {
cardRefs.current[index].isExpanded = !cardRefs.current[index].isExpanded; // 切换展开状态
const updatedHeight = cardRefs.current[index].isExpanded
? SCREEN_HEIGHT * 0.65
: CARD_HEIGHT;
console.log(
"已展开",
cardRefs.current[index],
animateCardAll.current[index],
animateCardAll,
updatedHeight
);
Animated.timing(animateCardAll.current[index], {
toValue: updatedHeight,
duration: 500,
useNativeDriver: false,
}).start();
};
正如我提到的,animateCardAll.current[index] 中的值已经正确更新,但没有触发任何动画。另外,我正在遵循此链接上的示例Example。
英文:
Thank you for the post. So I am following this example on my code, but my animation is not being triggered for some reason. The array from the useRef is being changed, but the animation is not working, any ideas of what could be the issue, here is my code. I am trying to expand my card to make the height bigger whenever the user press the View Information button. Thank you!
const animateCardAll = useRef([]);
{markersArr.map((marker, index) => {
animateCardAll.current[index] = new Animated.Value(CARD_HEIGHT);
marker.isExpanded = false;
(marker.imageFetched = false), console.log(marker);
return (
<>
<Animated.View
key={marker._id}
style={[
styles.card,
{
height: animateCardAll.current[index],
},
]}
>
{marker.imageId ? (
<LazyImage
index={index}
//visibleImages={visibleImages}
imageId={marker.imageId}
userToken={userToken}
ref={(cardRefs.current[index] = marker)}
/>
) : null}
<View style={styles.textContent}>
<Text style={styles.cardTitle} numberOfLines={1}>
Address: {marker.address}
</Text>
<Text style={styles.cardDescription} numberOfLines={1}>
{marker.city}, {marker.zip_code} {marker.uSstate}
</Text>
{cardRefs.current[index] &&
cardRefs.current[index].isExpanded ? (
<ReviewsComponent
index={index}
addressId={marker._id}
userToken={userToken}
/>
) : null}
</View>
<View style={styles.button}>
<TouchableOpacity
onPress={() => {
expandCardAll(index);
}}
style={[
styles.signIn,
{
borderColor: "#398984",
borderWidth: 1,
},
]}
>
<Text
style={[
styles.textSign,
{
color: "#398984",
},
]}
>
VIEW INFORMATION
</Text>
</TouchableOpacity>
</View>
</Animated.View>
</>
);
})}
</Animated.ScrollView>
) : null}
const expandCardAll = (index) => {
cardRefs.current[index].isExpanded = !cardRefs.current[index].isExpanded; // Toggle the expanded state
const upadtedHeight = cardRefs.current[index].isExpanded
? SCREEN_HEIGHT * 0.65
: CARD_HEIGHT;
console.log(
"Expanded",
cardRefs.current[index],
animateCardAll.current[index],
animateCardAll,
upadtedHeight
);
Animated.timing(animateCardAll.current[index], {
toValue: upadtedHeight,
duration: 500,
useNativeDriver: false,
}).start(); };
As I mentioned, the value in my animateCardAll.current[index] is being updated properly, but no animation is being triggered. Also, I am following the example on this link Example
答案1
得分: 1
从您提供的代码片段来看,似乎每次组件重新渲染时,您都为数组中的每个项目创建了一个新的Animated.Value。这是因为Animated.Value的初始化在map函数内部,而map函数又位于渲染方法内部。我认为这可能是您的动画不按预期工作的原因。
相反,您应该只初始化每个项目的Animated.Value一次,然后使用这些值来动画化项目。您可以这样做:
const animateCardAll = useRef(markersArr.map(() => new Animated.Value(CARD_HEIGHT)));
const expandCardAll = (index) => {
const updatedHeight = cardRefs.current[index].isExpanded
? SCREEN_HEIGHT * 0.65
: CARD_HEIGHT;
Animated.timing(animateCardAll.current[index], {
toValue: updatedHeight,
duration: 500,
useNativeDriver: false,
}).start();
};
return (
<Animated.ScrollView>
{markersArr.map((marker, index) => (
<Animated.View
key={marker._id}
style={[
styles.card,
{
height: animateCardAll.current[index],
},
]}
>
{/* ...rest of your code... */}
</Animated.View>
))}
</Animated.ScrollView>
);
animateCardAll
是一个引用,其中包含一组Animated.Value实例,每个实例对应markersArr中的一个项目。expandCardAll函数更新指定项目的Animated.Value并启动动画。每个卡片的高度都设置为其对应的Animated.Value,因此当值更改时,它会进行动画处理。
我假设markersArr数组在组件挂载后不会更改。如果数组中的项目可以添加或删除,您需要单独处理这个问题,例如使用状态变量来存储Animated.Value实例,并在数组更改时更新它们。希望这有所帮助!
英文:
From the code snippet you've provided, it seems like you're creating a new Animated.Value for each item in the array every time the component re-renders. This is because of the Animated.Value initialization is inside the map function which is inside the render method. I think it could be the reason why your animations are not working as expected.
Instead, you should initialize the Animated.Value for each item only once, and then use these values to animate the items. You might do that:
const animateCardAll = useRef(markersArr.map(() => new Animated.Value(CARD_HEIGHT)));
const expandCardAll = (index) => {
const updatedHeight = cardRefs.current[index].isExpanded
? SCREEN_HEIGHT * 0.65
: CARD_HEIGHT;
Animated.timing(animateCardAll.current[index], {
toValue: updatedHeight,
duration: 500,
useNativeDriver: false,
}).start();
};
return (
<Animated.ScrollView>
{markersArr.map((marker, index) => (
<Animated.View
key={marker._id}
style={[
styles.card,
{
height: animateCardAll.current[index],
},
]}
>
{/* ...rest of your code... */}
</Animated.View>
))}
</Animated.ScrollView>
);
animateCardAll
is a ref that holds an array of Animated.Value instances, one for each item in markersArr. The expandCardAll function updates the Animated.Value for the specified item and starts the animation. The height of each card is set to its corresponding Animated.Value, so it will animate when the value changes.
I assume that the markersArr array does not change after the component mounts. If items can be added or removed from the array, you'll need to handle that separately, for example by using a state variable to store the Animated.Value instances and update them when the array changes. Hope it works mate!
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论