Home > Back-end >  React Native Scrollview - scroll one by one (items with different widths)
React Native Scrollview - scroll one by one (items with different widths)

Time:11-01

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?

enter image description here

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,
 },
});
  • Related