繁体   English   中英

如何在本机反应中制作带有钩子的无限图像轮播

[英]how to make an infinite image carousel with hooks in react native

我正在使用钩子和 javascript 在本机反应中制作无限图像轮播。

我几乎完成了代码,轮播也工作得很好,但轮播下方的活动点比图像运行得更快。 我已经尝试了几件事,但不幸的是它没有成功。

提前致谢。

import React, {
  useEffect,
  useState,
  useRef,
  useCallback,
  createRef,
} from 'react';
import {
  StyleSheet,
  View,
  Dimensions,
  FlatList,
  LayoutAnimation,
  UIManager,
  Text,
} from 'react-native';
import {ActivityIndicator} from 'react-native';
import {Image} from 'react-native-elements';

const HomeCarousel = ({data}) => {
  const [dimension, setDimension] = useState(Dimensions.get('window'));
  const [index, setIndex] = useState(0);
  const [dataState, setDataState] = useState(data);

  slider = createRef();
  let intervalId = null;

  const onChange = () => {
    setDimension(Dimensions.get('window'));
  };

  useEffect(() => {
    Dimensions.addEventListener('change', onChange);
    return () => {
      Dimensions.removeEventListener('change', onChange);
    };
  });

  useEffect(() => {
    if (Platform.OS === 'android') {
      UIManager.setLayoutAnimationEnabledExperimental(true);
    }
  }, []);

  viewabilityConfig = {
    viewAreaCoveragePercentThreshold: 50,
  };

  const onViewableItemsChanged = ({viewableItems, changed}) => {
    if (viewableItems.length > 0) {
      let currentIndex = viewableItems[0].index;
      if (currentIndex % data.length === data.length - 1) {
        setIndex(currentIndex),
          setDataState(dataState => [...dataState, ...data]);
      } else {
        console.log(currentIndex, 'else');
        setIndex(currentIndex);
      }
    }
  };

  const onSlideChange = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeIn);

    const newIndex = index + 1;
    setIndex(newIndex);

    slider?.current?.scrollToIndex({
      index: index,
      animated: true,
    });
  };

  const startInterval = useCallback(() => {
    intervalId = setInterval(onSlideChange, 3000);
  }, [onSlideChange]);

  useEffect(() => {
    startInterval();

    return () => {
      clearInterval(intervalId);
    };
  }, [onSlideChange]);

  const viewabilityConfigCallbackPairs = useRef([
    {viewabilityConfig, onViewableItemsChanged},
  ]);

  const renderIndicator = ()=>{
    const indicators = [];
    data.map((val,key)=>(
      indicators.push(
        <Text
        key={key}
        style={
          key === index % data.length ? {color: 'lightblue',fontSize:10,marginBottom: 8,marginHorizontal:1} :
          {color: '#888',fontSize:10,marginBottom: 8,marginHorizontal:1}
        }>
        ⬤
      </Text>
      )
    ));
    return indicators;
  }

  return (
    <View style={{width: dimension.width,height: 280, backgroundColor: '#fff'}}>
      <FlatList
        ref={slider}
        horizontal
        pagingEnabled
        snapToInterval={dimension?.width}
        decelerationRate="fast"
        bounces={false}
        showsHorizontalScrollIndicator={false}
        data={dataState}
        renderItem={({item, index}) => (
          <>
            <View>
              <Image
                source={{uri: `${item.url}`}}
                style={{
                  width: dimension?.width,
                  height: 250,
                  resizeMode: 'cover',
                }}
                PlaceholderContent={<ActivityIndicator />}
              />
            </View>
          </>
        )}
        viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs.current}
        getItemLayout={(data, index) => ({
          length: dimension?.width,
          offset: dimension?.width * index,
          index,
        })}
        windowSize={1}
        initialNumToRender={1}
        maxToRenderPerBatch={1}
        removeClippedSubviews={true}
      />
      <View
        style={{
          flexDirection: 'row',
          position: 'absolute',
          bottom: 0,
          alignSelf: 'center',
        }}>
        {renderIndicator()}
      </View>
    </View>
  );
};

const styles = StyleSheet.create({});

export default HomeCarousel;


作为道具传递给该组件的数据是

export const carouselImages = [
  {url: 'https://i.ibb.co/FDwNR9d/img1.jpg'},
  {url: 'https://i.ibb.co/7G5qqGY/1.jpg'},
  {url: 'https://i.ibb.co/Jx7xqf4/pexels-august-de-richelieu-4427816.jpg'},
  {url: 'https://i.ibb.co/GV08J9f/pexels-pixabay-267202.jpg'},
  {url: 'https://i.ibb.co/sK92ZhC/pexels-karolina-grabowska-4210860.jpg'},
];

Ooooooh,我自己修复了这是完美工作的代码完整代码。

import React, {
  useEffect,
  useState,
  useRef,
  useCallback,
  createRef,
} from 'react';
import {
  StyleSheet,
  View,
  Dimensions,
  FlatList,
  LayoutAnimation,
  UIManager,
  Text,
} from 'react-native';
import {ActivityIndicator} from 'react-native';
import {Image} from 'react-native-elements';

const HomeCarousel = ({data}) => {
  const [dimension, setDimension] = useState(Dimensions.get('window'));
  const [index, setIndex] = useState(0);
  const [dataState, setDataState] = useState(data);
  const [indicatorIndex, setindicatorIndex] = useState();

  slider = createRef();
  let intervalId = null;

  const onChange = () => {
    setDimension(Dimensions.get('window'));
  };

  useEffect(() => {
    Dimensions.addEventListener('change', onChange);
    return () => {
      Dimensions.removeEventListener('change', onChange);
    };
  });

  useEffect(() => {
    if (Platform.OS === 'android') {
      UIManager.setLayoutAnimationEnabledExperimental(true);
    }
  }, []);

  viewabilityConfig = {
    viewAreaCoveragePercentThreshold: 50,
  };

  const onViewableItemsChanged = ({viewableItems, changed}) => {
    if (viewableItems.length > 0) {
      let currentIndex = viewableItems[0].index;
      if (currentIndex % data.length === data.length - 1) {
        setIndex(currentIndex), setindicatorIndex(currentIndex);
        setDataState(dataState => [...dataState, ...data]);
      } else {
        console.log(currentIndex, 'else');
        setIndex(currentIndex);
        setindicatorIndex(currentIndex);
      }
    }
  };

  const onSlideChange = () => {
    LayoutAnimation.configureNext(LayoutAnimation.Presets.easeIn);

    const newIndex = index + 1;
    setIndex(newIndex);

    slider?.current?.scrollToIndex({
      index: index,
      animated: true,
    });
  };

  const startInterval = useCallback(() => {
    intervalId = setInterval(onSlideChange, 3000);
  }, [onSlideChange]);

  useEffect(() => {
    startInterval();

    return () => {
      clearInterval(intervalId);
    };
  }, [onSlideChange]);

  const viewabilityConfigCallbackPairs = useRef([
    {viewabilityConfig, onViewableItemsChanged},
  ]);

  const renderIndicator = () => {
    const indicators = [];
    data.map((val, key) =>
      indicators.push(
        <Text
          key={key}
          style={
            key === indicatorIndex % data.length
              ? {
                  color: 'lightblue',
                  fontSize: 10,
                  marginBottom: 8,
                  marginHorizontal: 1,
                }
              : {
                  color: '#888',
                  fontSize: 10,
                  marginBottom: 8,
                  marginHorizontal: 1,
                }
          }>
          ⬤
        </Text>,
      ),
    );
    return indicators;
  };

  return (
    <View
      style={{width: dimension.width, height: 280, backgroundColor: '#fff'}}>
      <FlatList
        ref={slider}
        horizontal
        pagingEnabled
        snapToInterval={dimension?.width}
        decelerationRate="fast"
        bounces={false}
        showsHorizontalScrollIndicator={false}
        data={dataState}
        renderItem={({item, index}) => (
          <>
            <View>
              <Image
                source={{uri: `${item.url}`}}
                style={{
                  width: dimension?.width,
                  height: 250,
                  resizeMode: 'cover',
                }}
                PlaceholderContent={<ActivityIndicator />}
              />
            </View>
          </>
        )}
        viewabilityConfigCallbackPairs={viewabilityConfigCallbackPairs.current}
        getItemLayout={(data, index) => ({
          length: dimension?.width,
          offset: dimension?.width * index,
          index,
        })}
        windowSize={1}
        initialNumToRender={1}
        maxToRenderPerBatch={1}
        removeClippedSubviews={true}
      />
      <View
        style={{
          flexDirection: 'row',
          position: 'absolute',
          bottom: 0,
          alignSelf: 'center',
        }}>
        {renderIndicator()}
      </View>
    </View>
  );
};

const styles = StyleSheet.create({});

export default HomeCarousel;

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM