React-Native 循环轮播图,最后一张到第一张,会重新加载并闪烁的完美解决方案

705 阅读2分钟

在ReactNative的开发工作中,为了实现循环轮播图的效果,苦苦寻找了很多的轮播插件,实现了效果,但是仔细一看,最后一张到第一张,总会重新加载,并造成闪烁的效果,这肯定不符合需求。

插件选择:为了最小成本并快速解决这个问题,我选择了[react-native-swiper-flatlist](react-native-swiper-flatlist - npm (npmjs.com))

实现思路:既然,循环你会重复重新加载,那么我们不启用循环,属性设置为loop={false},这时候我们自己监听滑动到最后一个,并用插件提供的方法让他回到第2个并关闭动画。如果滑到第一个,则让其回到倒数第二个并关闭动画(为了实现最佳效果,我们需要给图片数组的最后,手动添加一项第一张图片,数组最前面,添加原数组的最后一项)

好了,上代码吧

import React, { useRef } from 'react'
import { Dimensions, StyleSheet, View } from 'react-native'
import { SwiperFlatList } from 'react-native-swiper-flatlist'
import FastImage from 'react-native-fast-image'

// 复制第一个图片地址,并添加到数组最后
const colors =['https://t7.baidu.com/it/u=91673060,7145840&fm=193&f=GIF', // 原数组的最后一项
'https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF', 'https://t7.baidu.com/it/u=963301259,1982396977&fm=193&f=GIF', 'https://t7.baidu.com/it/u=737555197,308540855&fm=193&f=GIF', 'https://t7.baidu.com/it/u=91673060,7145840&fm=193&f=GIF', 'https://t7.baidu.com/it/u=1819248061,230866778&fm=193&f=GIF', // 原数组的第一项
]

const App = () => {
  const BannerRef = useRef(null)
  const onChangeIndex = (e) => {
    // 监听到滚动到最后一项,马上滚动到第2个,并关闭动画,animated: false
    if (e.index == data.length - 1) {
      setTimeout(() => {
        BannerRef?.current?.scrollToIndex({ index: 1, animated: false })
      }, 200)
    }
    // 监听到滚动到第一项,马上滚动到倒数第2个,并关闭动画,animated: false
    if (e.index == 0) {
      setTimeout(() => {
        BannerRef?.current?.scrollToIndex({ index: data.length - 2, animated: false })
      }, 200)
    }
  }

  return <View style={styles.container}>
    <SwiperFlatList
      ref={BannerRef}
      autoplay
      autoplayDelay={3}
      autoplayLoop
      index={1}
      data={colors}
      renderAll={true}
      removeClippedSubviews={false} //这个很重要这个是设置离开可见区域不卸载不然还是会有闪烁问题
      onChangeIndex={onChangeIndex}
      renderItem={({ item }) => (
        <View style={[styles.child]}>
          <FastImage style={{ width: '100%', height: '100%' }} source={{ uri: item }} />
        </View>
      )}
    />
  </View>
}

const { width } = Dimensions.get('window')
const styles = StyleSheet.create({
  container: { flex: 1, backgroundColor: 'white', height: 400 },
  child: { width, justifyContent: 'center' },
  text: { fontSize: width * 0.5, textAlign: 'center' },
})

export default App

好了,问题解决,去试试效果吧