在React Native中对映射中的单个卡片进行动画处理。

huangapple go评论71阅读模式
英文:

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) =&gt; {
animateCardAll.current[index] = new Animated.Value(CARD_HEIGHT);
marker.isExpanded = false;
(marker.imageFetched = false), console.log(marker);
return (
&lt;&gt;
&lt;Animated.View
key={marker._id}
style={[
styles.card,
{
height: animateCardAll.current[index],
},
]}
&gt;
{marker.imageId ? (
&lt;LazyImage
index={index}
//visibleImages={visibleImages}
imageId={marker.imageId}
userToken={userToken}
ref={(cardRefs.current[index] = marker)}
/&gt;
) : null}
&lt;View style={styles.textContent}&gt;
&lt;Text style={styles.cardTitle} numberOfLines={1}&gt;
Address: {marker.address}
&lt;/Text&gt;
&lt;Text style={styles.cardDescription} numberOfLines={1}&gt;
{marker.city}, {marker.zip_code} {marker.uSstate}
&lt;/Text&gt;
{cardRefs.current[index] &amp;&amp;
cardRefs.current[index].isExpanded ? (
&lt;ReviewsComponent
index={index}
addressId={marker._id}
userToken={userToken}
/&gt;
) : null}
&lt;/View&gt;
&lt;View style={styles.button}&gt;
&lt;TouchableOpacity
onPress={() =&gt; {
expandCardAll(index);
}}
style={[
styles.signIn,
{
borderColor: &quot;#398984&quot;,
borderWidth: 1,
},
]}
&gt;
&lt;Text
style={[
styles.textSign,
{
color: &quot;#398984&quot;,
},
]}
&gt;
VIEW INFORMATION
&lt;/Text&gt;
&lt;/TouchableOpacity&gt;
&lt;/View&gt;
&lt;/Animated.View&gt;
&lt;/&gt;
);
})}
&lt;/Animated.ScrollView&gt;
) : null}
const expandCardAll = (index) =&gt; {
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(
&quot;Expanded&quot;,
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(() =&gt; new Animated.Value(CARD_HEIGHT)));
const expandCardAll = (index) =&gt; {
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 (
&lt;Animated.ScrollView&gt;
{markersArr.map((marker, index) =&gt; (
&lt;Animated.View
key={marker._id}
style={[
styles.card,
{
height: animateCardAll.current[index],
},
]}
&gt;
{/* ...rest of your code... */}
&lt;/Animated.View&gt;
))}
&lt;/Animated.ScrollView&gt;
);

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!

huangapple
  • 本文由 发表于 2023年6月12日 12:58:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/76453748.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定