基于react native的自定义轮播图

基于react native的自定义轮播图

效果示例图

在这里插入图片描述

示例代码

import React, {useEffect, useRef, useState} from 'react';
import {
  Animated,
  PanResponder,
  StyleSheet,
  Text,
  View,
  Dimensions,
} from 'react-native';
import {pxToPd} from '../../common/js/device';

const TestSwiper = () => {
  //动态获取的值
  const [tempList, setTempList] = useState([
    {id: 1},
    {id: 2},
    {id: 3},
    {id: 4},
  ]);

  const [swiperList, setSwiperList] = useState([]);
  const swiperListRef = useRef([]);
  //定时器手柄
  const intervalHandleRef = useRef(null);
  //手势滑动区域节点
  const animatedViewRef = useRef(null);
  //单个切换页面的宽度
  const deviceWidth = Dimensions.get('window').width;
  // 默认显示下标的页面
  let currentIndexRef = useRef(0);
  const panResponderEnabled = useRef(true);

  //滑动的距离
  const defaultMove = -currentIndexRef.current * deviceWidth;
  const pan = useRef(new Animated.Value(defaultMove)).current;

  //手势操作
  const panResponder = useRef(
    PanResponder.create({
      onStartShouldSetPanResponder: () => true,
      onPanResponderGrant: () => {
        clearInterval(intervalHandleRef.current); // 暂停自动轮播
        panResponderEnabled.current = true;
      },
      //处理手势移动事件,其中使用了`dx`参数来表示在x轴上的移动距离
      onPanResponderMove: (evt, gestureState) => {
        //获取当前滚动区域有几个孩子节点
        const count = animatedViewRef.current._children.length;
        //每次移动的距离
        const moveX = -currentIndexRef.current * deviceWidth;
        //当移动到最左侧或者最右侧时,禁止拖动
        const start = currentIndexRef.current == 0 && gestureState.dx > 0;
        const end = currentIndexRef.current == count - 1 && gestureState.dx < 0;
        if (start || end) {
          // 禁止继续拖动
          return false;
        }
        pan.setValue(moveX + gestureState.dx);
        if (panResponderEnabled.current) {
          panResponderEnabled.current = false; // 防止多次暂停自动轮播
          clearInterval(intervalHandleRef.current); // 暂停自动轮播
        }
      },
      //处理手势释放时的逻辑
      onPanResponderRelease: (_, gestureState) => {
        //获取当前滚动区域有几个孩子节点
        const count = animatedViewRef.current._children.length;
        //当手指拖动区域大于100的时候,开始切换页面
        if (Math.abs(gestureState.dx) > 100) {
          let newPageIndex = currentIndexRef.current;
          if (gestureState.dx > 0) {
            newPageIndex = Math.max(0, currentIndexRef.current - 1);
          } else {
            newPageIndex = Math.min(count - 1, currentIndexRef.current + 1);
          }
          const moveX = -newPageIndex * deviceWidth;
          currentIndexRef.current = newPageIndex;

          Animated.timing(pan, {
            toValue: moveX,
            duration: 300,
            useNativeDriver: true,
          }).start(() => {
            if (newPageIndex == count - 1) {
              currentIndexRef.current = 0;
              pan.setValue(0);
            }
            autoPlayAPI(); // 继续自动轮播
          });
        } else {
          pan.setValue(-currentIndexRef.current * deviceWidth);
        }
        if (!panResponderEnabled.current) {
          autoPlayAPI(); // 继续自动轮播
        }
      },
    }),
  ).current;

  //自动轮播
  const autoPlayAPI = () => {
    const max = swiperListRef.current.length - 1;
    if (intervalHandleRef.current) {
      clearInterval(intervalHandleRef.current);
    }
    intervalHandleRef.current = setInterval(() => {
      let newPageIndex = 0;
      if (currentIndexRef.current == max) {
        newPageIndex = 0;
      } else {
        newPageIndex = currentIndexRef.current + 1;
      }
      const moveX = -newPageIndex * deviceWidth;
      currentIndexRef.current = newPageIndex;
      Animated.timing(pan, {
        toValue: moveX,
        duration: 300,
        useNativeDriver: true,
      }).start(() => {
        if (newPageIndex == max) {
          currentIndexRef.current = 0;
          pan.setValue(0);
          autoPlayAPI();
        }
      });
    }, 3000);
  };

  //初始化
  const initFunction = () => {
    let tempArr = [...tempList];
    let firstArr = tempArr[0];
    let contactArr = tempArr.concat(firstArr);
    swiperListRef.current = contactArr;
    setSwiperList(() => contactArr);
    autoPlayAPI();
  };

  useEffect(() => {
    initFunction();

    return () => {
      clearInterval(intervalHandleRef.current);
    };
  }, []);
  return (
    <>
      <View style={styles.swiperWrap}>
        <Animated.View
          ref={animatedViewRef}
          style={{
            width: deviceWidth * swiperList.length,
            flex: 1,
            flexDirection: 'row',
            transform: [{translateX: pan}],
            onStartShouldSetResponderCapture: () => false, // 禁止拦截触摸事件
          }}
          {...panResponder.panHandlers}>
          {swiperList.map((item, index) => (
            <View key={'swiperItem' + index} style={{width: deviceWidth}}>
              <View style={styles.swiperItem}>
                <Text>item {item.id}</Text>
              </View>
            </View>
          ))}
        </Animated.View>
      </View>
    </>
  );
};

const styles = StyleSheet.create({
  swiperWrap: {
    borderColor: 'red',
    borderWidth: pxToPd(1),
    borderStyle: 'solid',
    width: '100%',
    height: pxToPd(400),
  },
  swiperItem: {
    borderColor: 'red',
    borderWidth: pxToPd(1),
    borderStyle: 'solid',
    borderRadius: pxToPd(12),
    width: '93.6%',
    marginLeft: '3.2%',
    height: '100%',
  },
});

export default TestSwiper;


相关推荐

  1. 制作

    2024-03-22 15:04:03       60 阅读
  2. Swiper

    2024-03-22 15:04:03       39 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-03-22 15:04:03       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-03-22 15:04:03       101 阅读
  3. 在Django里面运行非项目文件

    2024-03-22 15:04:03       82 阅读
  4. Python语言-面向对象

    2024-03-22 15:04:03       91 阅读

热门阅读

  1. 大型语言模型(LLM)全解读

    2024-03-22 15:04:03       39 阅读
  2. 【DataWhale学习笔记-蝴蝶书共读】文本生成

    2024-03-22 15:04:03       39 阅读
  3. L2-011 玩转二叉树(数组建树)

    2024-03-22 15:04:03       36 阅读
  4. go执行go mod tidy时报错连接失败(go换依赖源)

    2024-03-22 15:04:03       38 阅读
  5. git 问题

    2024-03-22 15:04:03       47 阅读
  6. 基于PyTorch深度学习实战入门系列-PyTorch基础上

    2024-03-22 15:04:03       41 阅读
  7. python基础学习第一天

    2024-03-22 15:04:03       43 阅读
  8. 在Hive中使用Python编写的UDF函数

    2024-03-22 15:04:03       41 阅读