android – ScrollToIndex not working on the 0 index (React Native


Currently what is happening right is that I have 4 categories namely : all , category 1, category 2 and category 3

Now here’s the scenario If i am from the all category and choose category 1 the scroll effect animation works perfect same goes to all -> category 2, all -> category 3 or category 1 -> category 2 and so on.

Now if I do it inverted like from category 3 -> category 2 it works fine also but when I tried category 3 or category 2 -> all category the scroll effect animation doesn’t work.

Here’s my code

interface Item {
  id: string;
  title: string;
}

const getItemMargin = (isFirstIndex: boolean, isLastIndex: boolean) => {
  return {
    marginLeft: isFirstIndex ? 24 : 0,
    marginRight: isLastIndex ? 24 : 8,
  };
};

interface CSProps<T extends Item> extends ViewProps {
  items: T[];
  onSelectItem: (id: T['id']) => void;
  selectedId: string;
  // categoryIndex: number;
}

const CategoryList = <T extends Item>({
  style,
  items,
  onSelectItem,
  selectedId,
  // categoryIndex,
  ...rest
}: CSProps<T>): JSX.Element => {
  const {t} = useTranslation();
  const flatList = useRef<FlatList>(null);
  const [cIndex, setCIndex] = useState<number>(0);

  useEffect(() => {
    if (selectedId === 'all') {
      setCIndex(0);
    } else if (selectedId === 'category 1') {
      setCIndex(1);
    } else if (selectedId === 'category 2') {
      setCIndex(2);
    } else {
      setCIndex(3);
    }

    const timeout = setTimeout(() => {
      console.log(`Check cIndex : ${cIndex}`);
      flatList?.current?.scrollToIndex({
        index: cIndex,
        animated: true,
        viewOffset: 10,
      });
    }, 100); // You can adjust the delay as needed

    return () => clearTimeout(timeout);
  }, [cIndex, items.length, selectedId]);

  /**
   * For smooth transition of category tab on FlatList
   * @param data
   * @param index
   * @returns
   */
  const getItemLayout = (data: any, index: any) => {
    return {
      length: styles.item.height,
      offset: styles.item.height * index,
      index,
    };
  };

  const onMomentumScrollEnd = (event: any) => {
    const windowWidth = Dimensions.get('window').width;
    const currentIndex = Math.round(
      event.nativeEvent.contentOffset.x / windowWidth,
    );
    if (currentIndex !== cIndex) {
      console.log(`Check cIndex: ${currentIndex}`);
      setCIndex(currentIndex);
    }
  };

  const renderItem = ({item, index}: {item: T; index: Number}) => {
    const backgroundColor =
      item.id === selectedId
        ? Colors.PRIMARY_01_BLUE_4
        : Colors.PRIMARY_03_WHITE;
    const color =
      item.id === selectedId
        ? Colors.PRIMARY_03_WHITE
        : Colors.PRIMARY_01_BLUE_4;

    const borderWidth = item.id === selectedId ? 0 : 1;

    const isFirstIndex = index === 0;
    const isLastIndex = index === items.length - 1;

    return (
      <TouchableOpacity
        testID={item.title.replace(/[A-Z]/g, c => c.toLowerCase())}
        onPress={() => onSelectItem(item.id)}
        style={[
          styles.item,
          {backgroundColor},
          {borderWidth},
          getItemMargin(isFirstIndex, isLastIndex),
        ]}>
        <Text style={[styles.title, {color}]}>{t(item.title)}</Text>
      </TouchableOpacity>
    );
  };

  return (
    <View style={style} {...rest}>
      <FlatList
        ref={flatList}
        horizontal
        // initialScrollIndex={cIndex}
        data={items}
        renderItem={renderItem}
        keyExtractor={({id}) => String(id)}
        extraData={selectedId}
        showsHorizontalScrollIndicator={false}
        onMomentumScrollEnd={onMomentumScrollEnd}
        snapToAlignment="center"
        onScrollToIndexFailed={info =>
          setTimeout(() => {
            console.log(
              `Check if failed to scrollIndeX: ${JSON.stringify(info)}`,
            );
            flatList.current?.scrollToIndex({
              index: info.index,
              animated: false,
            });
          }, 500)
        }
        getItemLayout={getItemLayout}
      />
    </View>
  );
};

const styles = StyleSheet.create({
  input: {
    ...Typography.BODY_2_16_BOOK,
    borderBottomColor: Colors.PRIMARY_03_GREY_3,
    borderBottomWidth: 0.7,
    paddingVertical: 12,
  },
  inputActive: {
    borderBottomColor: Colors.PRIMARY_01_BLUE_4,
  },
  item: {
    borderRadius: 16,
    borderStyle: 'solid',
    borderColor: Colors.PRIMARY_03_GREY_3,
    paddingHorizontal: 16,
    height: 28,
    justifyContent: 'center',
    alignItems: 'flex-start',
  },
  title: {
    ...Typography.REMARK_1_13_MEDIUM,
  },
});

Latest articles

spot_imgspot_img

Related articles

Leave a reply

Please enter your comment!
Please enter your name here

spot_imgspot_img