我在水平 FlatList 中显示了不同的项目列表。 所以基本上我有不同的列表:
它们都是水平的,并且共享相同的逻辑。
我正在使用 Animated 根据项目的索引通过插值为 flatlist 设置动画。
它可以正常显示某些列表但不能显示其他列表,例如索引会因一个列表而异,但我不明白发生了什么,因为所有列表都应从索引 [0] 开始
这里你可以看一个截图来理解: FlatList bug display
如您所见,第一个列表正确显示在屏幕上,并被插值为正常大小的 1.3 倍,但第二个共享完全相同的逻辑没有被插值。
三个主要组成部分:
已编辑(添加此块) BlockHomeChanelList:
export default function BlockHomeChannelList({ showModal = false, startSlice = 0, endSlice = 1 }) {
const categories = useSelector(getCategoriesList);
return (
<SectionList
contentContainerStyle={{ marginLeft: MixinsStyles.wp(0) }}
scrollEnabled={false}
sections={categories.slice(startSlice, endSlice)}
keyExtractor={(item) => item.id + item.name}
renderItem={({ item, section: { name } }) => (
<BlockHomeChannelItem
showPlus={true}
showModal={showModal}
categoryItem={item}
name={name}
/>
)}
/>
);
}
在该示例中,仅显示一个类别(通过使用幻灯片),并且在该类别内有四个列表。 像一个类别(体育):和显示在水平平面列表中的子类别(篮子、脚、曲棍球......)
阻止家庭频道列表:
export default function BlockHomeChannelItem({
categoryItem,
titleButton = "Voir toutes les vidéos",
name,
// showPlus = false,
}) {
const navigation = useNavigation();
const token = useSelector((state) => state.user.tokens.token);
const [loading, setLoading] = React.useState(false);
const [playlist, setPlaylist] = React.useState({});
// Flatlist
const CARD_WIDTH = MixinsStyles.wp(196);
const AnimatedFlatList = Animated.createAnimatedComponent(FlatList);
const animated = useRef(new Animated.Value(0)).current;
const padding = (width - CARD_WIDTH) / 2;
const marginRight = MixinsStyles.wp(18);
const flatListRef = useRef(null);
React.useEffect(() => {
if (token && categoryItem.id && !playlist?.id) {
getChannelPlaylist(token, categoryItem.id).then((data) => {
setPlaylist(data);
setLoading(false);
});
}
}, [token, categoryItem.id, playlist?.id]);
if (loading || !playlist?.videos?.length || !playlist?.activeVideoCount) {
return null;
}
return (
<View style={{ marginBottom: MixinsStyles.hp(35) }}>
*...TextTitleCode*
<AnimatedFlatList
data={playlist?.videos}
horizontal
ref={flatListRef}
showsHorizontalScrollIndicator={false}
keyExtractor={(item) => item}
onScroll={Animated.event(
[
{
nativeEvent: {
contentOffset: {
x: animated,
},
},
},
],
{ useNativeDriver: true }
)}
scrollEventThrottle={16}
getItemLayout={(data, index) => ({
length: CARD_WIDTH + marginRight,
offset: (CARD_WIDTH + marginRight) * index,
index,
})}
snapToInterval={CARD_WIDTH + marginRight}
contentContainerStyle={{ paddingHorizontal: padding, height: MixinsStyles.hp(200) }}
renderItem={({ item, index }) => {
const inputRange = [
(index - 1) * (CARD_WIDTH + marginRight), //
index * (CARD_WIDTH + marginRight),
(index + 1) * (CARD_WIDTH + marginRight),
];
const scale = animated.interpolate({
inputRange,
outputRange: [1, 1.28, 1],
extrapolate: "clamp",
});
const opacity = animated.interpolate({
inputRange,
outputRange: [0.5, 1, 0.5],
extrapolate: "clamp",
});
const myScale = { transform: [{ scale }] };
return (
<BlockVideo
showModal={showModal}
item={item}
resume={resume}
favorite={favorite}
animatedStyle={{ opacity, myScale }}
/>
);
}}
/>
*....buttonCode*
</View>
);
}
块视频:
export default function BlockVideo({
item,
resume,
favorite,
animatedStyle,
}) {
const dispatch = useDispatch();
const navigation = useNavigation();
const video = useSelector((state) =>
state.videos.filter((element) => !!element.active).find((element) => element["@id"] === item)
);
if (!video?.id) {
return null;
}
return (
<Animated.View
style={[
animatedStyle.myScale,
{
opacity: animatedStyle.opacity,
alignSelf: "center",
marginRight: MixinsStyles.wp(36),
},
]}
>
<TouchableOpacity
onPress={...code}
>
<ImageBackground
borderRadius={5}
style={[
styles.containerImageBackground,
{ width: search ? "100%" : MixinsStyles.hp(196) },
]}
source={
video?.picture?.contentUrl
? { uri: video?.picture?.contentUrl }
: AssetsImg.EXPERT_PICTURE
}
>
<GradientImageBackground variant="black" style={styles.gradientImage}>
{favorite && (
<AntDesign style={styles.iconFavorite} name="star" size={13} color="#FF0000" />
)}
<View style={styles.textPosition}>
<SharedText textAlign="center" size="12" family="bold">
{video?.name}
</SharedText>
{resume && <ProgressVideoBlock width={50} />}
</View>
</GradientImageBackground>
</ImageBackground>
</TouchableOpacity>
</Animated.View>
);
}
Stylesheet: {...some code}
如果我像这样改变输入范围,它会反转工作项目:
const inputRange = [
(index - 2) * (CARD_WIDTH + marginRight), //
(index -1) * (CARD_WIDTH + marginRight),
(index) * (CARD_WIDTH + marginRight),
];
所以问题是如何为我的所有列表正确显示项目? 我的代码出了什么问题?
非常感谢
答案 0 :(得分:0)
好的,所以我发现了我的代码出了什么问题。 flatlist 背后的逻辑很好。
问题出在最后一个组件“BlockVideo”上,这里:
const video = useSelector((state) =>
state.videos.filter((element) => !!element.active).find((element) => element["@id"] === item)
);
if (!video?.id) {
return null;
}
由于它通过 id 过滤元素并且不显示没有 id 的项目,元素的索引仍然相同,但屏幕上没有显示任何内容,从而产生了间隙