Open JoshTechLee opened 4 months ago
Hey @JoshTechLee! I'm here to help you with any bugs, questions, or contributions. Let's tackle this issue together!
To fix the issue where a nested horizontal FlatList within a horizontal Carousel component scrolls the carousel instead of the FlatList on Android, you can adjust the activeOffsetX
of the gesture handler for the Carousel. This will ensure that the x-axis is free and does not impede the scroll of the FlatList.
Here is an example of how you can configure the activeOffsetX
:
import * as React from "react";
import type { ICarouselInstance } from "react-native-reanimated-carousel";
import Carousel from "react-native-reanimated-carousel";
import { SafeAreaView } from "react-native-safe-area-context";
import { getImages } from "../../utils/get-images";
import SButton from "../../components/SButton";
import { ElementsText, window } from "../../constants";
import { useWindowDimensions, View, FlatList, StyleSheet } from "react-native";
import Animated, { Extrapolation, interpolate, useSharedValue, useAnimatedStyle } from "react-native-reanimated";
import { GestureHandlerRootView } from "react-native-gesture-handler";
const PAGE_WIDTH = window.width;
const LARGE_IMAGE_WIDTH = PAGE_WIDTH * 0.5;
const MEDIUM_IMAGE_WIDTH = LARGE_IMAGE_WIDTH * 0.5;
const SMALL_IMAGE_WIDTH = MEDIUM_IMAGE_WIDTH * 0.5;
const COUNT = 3;
const data = getImages();
function Index() {
const windowWidth = useWindowDimensions().width;
const [isAutoPlay, setIsAutoPlay] = React.useState(false);
const ref = React.useRef<ICarouselInstance>(null);
const baseOptions = {
vertical: false,
width: windowWidth * 0.45,
height: PAGE_WIDTH / 1.5,
style: {
width: PAGE_WIDTH,
}
} as const;
const scrollX = useSharedValue<number>(0);
const onScroll = (offsetProgress: number) => {
scrollX.value = offsetProgress * -1;
};
return (
<GestureHandlerRootView style={{ flex: 1 }}>
<SafeAreaView edges={["bottom"]} style={{ flex: 1 }}>
<Carousel
{...baseOptions}
loop
enabled
ref={ref}
autoPlay={isAutoPlay}
data={data}
onProgressChange={onScroll}
renderItem={({ index, item }: any) => (
<Item
id={index}
img={item}
scrollX={scrollX}
/>
)}
onConfigurePanGesture={gestureChain => (
gestureChain.activeOffsetX([-10, 10])
)}
/>
<View style={{ flex: 1 }}>
<SButton
onPress={() => {
setIsAutoPlay(!isAutoPlay);
}}
>
{ElementsText.AUTOPLAY}:{`${isAutoPlay}`}
</SButton>
<SButton
onPress={() => {
ref.current?.scrollTo({ count: -1, animated: true });
}}
>
prev
</SButton>
<SButton
onPress={() => {
ref.current?.scrollTo({ count: 1, animated: true });
}}
>
next
</SButton>
</View>
</SafeAreaView>
</GestureHandlerRootView>
);
}
const Item = ({ id, img, scrollX }: { id: number, img: ImageSourcePropType, scrollX: any }) => {
const inputRange = [
(id - 2) * SMALL_IMAGE_WIDTH,
(id - 1) * SMALL_IMAGE_WIDTH,
id * SMALL_IMAGE_WIDTH,
(id + 1) * SMALL_IMAGE_WIDTH
];
const outputRange = [
SMALL_IMAGE_WIDTH,
MEDIUM_IMAGE_WIDTH,
LARGE_IMAGE_WIDTH,
SMALL_IMAGE_WIDTH
];
const animatedStyle = useAnimatedStyle(() => ({
width: interpolate(scrollX.value, inputRange, outputRange, Extrapolation.CLAMP)
}));
return (
<View style={styles.container}>
<Animated.Image
source={img}
style={[styles.image, animatedStyle]}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
marginVertical: 10,
},
image: {
width: PAGE_WIDTH,
height: 250,
borderRadius: 20,
marginRight: 10
}
});
export default Index;
This configuration will help in ensuring that the FlatList scrolls correctly within the Carousel. Additionally, wrapping the entire component in a GestureHandlerRootView
ensures that gesture handling is properly managed [1][2][3].
To continue talking to Dosu, mention @dosu.
In addition to bots comment, here is how I fixed it:
<GestureHandlerRootView style={styles.container}>
<ThemedView style={styles.container} noPadding>
<Carousel
defaultIndex={1}
loop={false}
width={width}
height={height}
data={dates}
onSnapToItem={onIndexChanged}
panGestureHandlerProps={{
activeOffsetX: [-20, 20],
}}
renderItem={({ item }) => (
<TransactionList date={item} key={item.getTime()} />
)}
/>
</ThemedView>
</GestureHandlerRootView>
I don't know which version does the bot refer to but I have found this
panGestureHandlerProps={{
activeOffsetX: [-20, 20],
}}
instead of this one here.
onConfigurePanGesture={gestureChain => (
gestureChain.activeOffsetX([-10, 10])
)}
panGestureHandlerProps={{ activeOffsetX: [-20, 20], }}
This one works
panGestureHandlerProps={{
activeOffsetX: [-20, 20],
}}
I have a nested horizontal FlatList within an also horizontal carousel component that will work on iOS but not on Android; when I try scrolling horizontally on the nested FlatList, the carousel moves instead. I've tried using the FlatList from react-native and from react-native-gesture-handler, both with
nestedScrollEnabled
but none seem to be doing the job.