在本教程中,我们将使用react-native-reanimated
创建一个动画可折叠卡。我们将从提供的模板开始,该模板可以在this GitHub link上找到。该模板包含一个带有lantlist的博览会项目。每个列表项目都有一个图像,标题和描述。我们的目标是使描述使用平稳的动画折叠。
##入门
首先,从github克隆该项目,然后切换到template
分支:
git clone https://github.com/dimaportenko/reanimated-collapsable-card-tutorial.git
cd reanimated-collapsable-card-tutorial
git checkout template
添加反应本机复活
我们将使用react-native-reanimated
库来创建我们的动画。要添加它,请运行以下命令:
npx expo install react-native-reanimated
然后,您需要更新您的babel.config.js
:
module.exports = function (api) {
api.cache(true);
return {
presets: ['babel-preset-expo'],
plugins: ['react-native-reanimated/plugin'],
};
};
执行
在我们的ListItem.tsx
中,我们将为可折叠内容的高度添加一个新状态:
const [height, setHeight] = useState(0);
const animatedHeight = useSharedValue(0);
我们计算onLayout
回调中的可折叠内容高度:
const onLayout = (event: LayoutChangeEvent) => {
const onLayoutHeight = event.nativeEvent.layout.height;
if (onLayoutHeight > 0 && height !== onLayoutHeight) {
setHeight(onLayoutHeight);
}
};
我们将为可折叠的内容创建动画样式:
const collapsableStyle = useAnimatedStyle(() => {
animatedHeight.value = expanded ? withTiming(height) : withTiming(0);
return {
height: animatedHeight.value,
};
}, [expanded]);
我们将把可折叠的内容包裹在Animated.View
中:
<Animated.View style={[collapsableStyle, {overflow: 'hidden'}]}>
<View style={{ position: 'absolute' }} onLayout={onLayout}>
<Text style={[styles.details, styles.text]}>{item.details}</Text>
</View>
</Animated.View>
要使我们的代码更可维护,让我们将CollapsableContainer
重构为一个可重复使用的组件:
import React, { useState } from "react";
import { LayoutChangeEvent, View, Text } from "react-native";
import Animated, {
useAnimatedStyle,
useSharedValue,
withTiming,
} from "react-native-reanimated";
export const CollapsableContainer = ({
children,
expanded,
}: {
children: React.ReactNode;
expanded: boolean;
}) => {
const [height, setHeight] = useState(0);
const animatedHeight = useSharedValue(0);
const onLayout = (event: LayoutChangeEvent) => {
const onLayoutHeight = event.nativeEvent.layout.height;
if (onLayoutHeight > 0 && height !== onLayoutHeight) {
setHeight(onLayoutHeight);
}
};
const collapsableStyle = useAnimatedStyle(() => {
animatedHeight.value = expanded ? withTiming(height) : withTiming(0);
return {
height: animatedHeight.value,
};
}, [expanded]);
return (
<Animated.View style={[collapsableStyle, { overflow: "hidden" }]}>
<View style={{ position: "absolute" }} onLayout={onLayout}>
{children}
</View>
</Animated.View>
);
};
那么,我们可以在ListItem
组件中使用我们的新CollapsableContainer
组件:
export const ListItem = ({ item }: { item: ListItemType }) => {
const [expanded, setExpanded] = useState(false);
const onItemPress = () => {
setExpanded(!expanded);
};
return (
<View style={styles.wrap}>
<TouchableWithoutFeedback onPress={onItemPress}>
<View style={styles.container}>
<Image source={{ uri: item.image }} style={styles.image} />
<View style={styles.textContainer}>
<Text style={styles.text}>{item.title}</Text>
<Text style={styles.text}>{item.subtitle}</Text>
</View>
</View>
</TouchableWithoutFeedback>
<CollapsableContainer expanded={expanded}>
<Text style={[styles.details, styles.text]}>{item.details}</Text>
</CollapsableContainer>
</View>
);
};
就是这样!您已经成功地使用react-native-reanimated
在React Native中成功创建了动画可折叠卡。该动画组件提供了流畅的用户体验,并且可以在应用程序的不同部分重复使用单独的CollapsableContainer
组件。愉快的编码! Final code