I have a horizontal ScrollView, all items have different widths
Is there a way to scroll one by one, so it would stop in the center of each item?
If the first answer to question is yes, then is there a way to know the index of item (that is centered), so I can change the index of selected dot?
CodePudding user response:
You can achieve this by react-native-snap-carousel and For dot, You can use pagination.
import Carousel, { Pagination } from 'react-native-snap-carousel';
const [active, setActive] = useState(0)
const [data, setData] = useState([])
<Carousel
keyExtractor={(_, index) => `id-${index}`}
data={data}
renderItem={renderItem}
onSnapToItem={setActive} />
<Pagination
dotsLength=length}
activeDotIndex={active}
dotStyle={{ backgroundColor: colors.blue }}
inactiveDotStyle={{ backgroundColor: colors.gray }}
inactiveDotScale={1}
inactiveDotOpacity={1} />
CodePudding user response:
Example for: https://i.stack.imgur.com/thKLv.gif
I'm using FlatList and its props.
More information: https://reactnative.dev/docs/flatlist
import * as React from "react";
import { StyleSheet, Dimensions, FlatList, Text, View } from "react-native";
const data = [
{
text: "Page1",
width: 300,
},
{
text: "Page2",
width: 250,
},
{
text: "Page3",
width: 200,
},
];
const DOT_SIZE = 8;
const { width } = Dimensions.get("window");
export default function App() {
const [indexDot, setIndexDot] = React.useState(0);
const onChangeDot = (event) => {
setIndexDot(Math.ceil(event.nativeEvent.contentOffset.x / width));
};
const renderPagination = React.useMemo(() => {
return (
<View style={styles.wrapPagination}>
{data.map((_, index) => {
return (
<View
key={index}
style={[
styles.dot,
{
backgroundColor:
indexDot === index ? "#E7537A" : "rgba(0, 0, 0, 0.3)",
},
]}
/>
);
})}
</View>
);
}, [data?.length, indexDot]);
const renderItem = ({ item }) => (
<View style={styles.wrapItem}>
<View
style={{
...styles.item,
width: item.width,
}}
>
<Text>{item.text}</Text>
</View>
</View>
);
return (
<>
<FlatList
horizontal
pagingEnabled
disableIntervalMomentum
showsHorizontalScrollIndicator={false}
data={data}
renderItem={renderItem}
scrollEventThrottle={200}
onMomentumScrollEnd={onChangeDot}
/>
{renderPagination}
</>
);
}
const styles = StyleSheet.create({
wrapPagination: {
flexDirection: "row",
flex: 1,
justifyContent: "center",
alignItems: "center",
},
dot: {
height: DOT_SIZE,
width: DOT_SIZE,
borderRadius: DOT_SIZE / 2,
marginHorizontal: 3,
},
wrapItem: {
width,
padding: 20,
alignItems: "center",
justifyContent: "center",
},
item: {
alignItems: "center",
justifyContent: "center",
borderWidth: 1,
},
});