平面列表中包含的每个项目的宽度等于屏幕宽度。当我向左或向右滑动时,我不喜欢自动捕捉动画效果。 具体来说,动画时长太短,有卡顿的感觉。
我尝试过使用内置的 flatlist 组件,例如“decelerationRate”和“snapToInterval”,但它们都没有达到预期的效果。 我也尝试过Reanimated库,但是找了很久文档,没有找到实现自定义动画的方法。 无论是Reanimated flatlist还是内置的flatlist的scrollTo方法,动画参数都只有“{animated: true}”等选项来切换动画,并没有办法调整时长。 如果你能帮助我,我将非常感激。我几天来一直在寻找解决方案。
如果您没有任何边距/填充,并且
<FlatList />
上的每个项目的宽度相同,则只需传递 pagingEnabled
、decelerationRate="fast"
和 snapToInterval
。但如果您有不同的项目宽度,您可能需要使用 snapToOffsets
(甚至 getItemLayout
)。
看看这个关于 Snack 的例子。
无论如何,如果您想快速查看,这里是源代码。
import React from 'react';
import { Animated, View, SafeAreaView, Dimensions } from 'react-native';
const itemWidth = 300;
const itemHeight = 400;
const screenWidth = Dimensions.get('screen').width;
const marginHorizontal = (screenWidth - itemWidth) / 2;
const colors = ['blue', 'brown', 'pink', 'purple'];
export default function App() {
const renderItem = React.useCallback(
({ item, index }: ListRenderItemInfo<RGBColor>) => {
return (
<View
style={{
height: itemHeight,
width: itemWidth,
backgroundColor: item,
flex: 1,
}}
/>
);
},
[]
);
const keyExtractor = React.useCallback(
(data, index) => `${index}-${data}`,
[]
);
/** In case you want more granular control over the item width */
const getItemLayout = React.useCallback(
(_, index) => ({
index,
length: itemWidth,
offset: itemWidth * index + marginHorizontal,
}),
[]
);
const snapToOffsets = React.useMemo(
() => colors.map((_, index) => itemWidth * (index + 1)),
[]
);
return (
<SafeAreaView
style={{
flex: 1,
justifyContent: 'center',
backgroundColor: '#ecf0f1',
height: itemHeight,
}}>
<Animated.FlatList
style={{ marginVertical: 20, height: itemHeight }}
contentContainerStyle={{
alignItem: 'center',
paddingHorizontal: marginHorizontal,
}}
pagingEnabled
snapToOffsets={snapToOffsets}
decelerationRate="fast"
snapToInterval
snapToAlignment="center"
horizontal
data={colors}
showsHorizontalScrollIndicator={false}
keyExtractor={keyExtractor}
renderItem={renderItem}
// getItemLayout={getItemLayout}
/>
<View
style={{
position: 'absolute',
top: 0,
start: 0,
end: 0,
alignItems: 'center',
justifyContent: 'center',
}}
pointerEvents="none">
<SafeAreaView
style={{
marginVertical: 20,
backgroundColor: 'rgba(255, 0, 0, 0.3)',
height: itemHeight,
width: itemWidth,
flex: 1,
borderWidth: 1,
borderColor: 'green',
borderRadius: 10,
}}
/>
</View>
</SafeAreaView>
);
}