ReactNative-Banner

本文展示了如何使用React Native创建一个动态轮播图组件,包括函数式和Class两种实现方式。组件实现了自动轮播、手动拖拽、滚动能监听等功能,并结合ImageData.json数据展示图片。同时,文章通过比较函数式组件和Class组件的实现,探讨了不同组件类型的使用场景。
摘要由CSDN通过智能技术生成

Banner

//函数式组件
let Banner = require('./Banner')
//Class组件
// let Banner2 = require('./Banner2');

const App: () => Node = () => {
  const isDarkMode = useColorScheme() === 'dark';

  const backgroundStyle = {
    backgroundColor: isDarkMode ? Colors.darker : Colors.lighter,
  };

  return (
    <SafeAreaView styles2={backgroundStyle}>
      <StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
      <Banner />
      {/*<Banner2 />*/}
    </SafeAreaView>
  );
};

Banner.js(函数式组件)

import React, { useState, useRef, useEffect } from "react";
import type {Node} from 'react';
import {
  ScrollView,
  StyleSheet,
  Text,
  View,
  Dimensions,
  Image,
} from 'react-native';

let {width, height, scale} = Dimensions.get('window');
let ImageData = require('./ImageData.json');

const Banner: () => Node = () => {
  const duration = 3000;
  const [currentPage, setCurrentPage] = useState(0);
  const scrollViewRef = useRef(null);
  const timerRef = useRef(null);

  // 相当于 componentDidMount 和 componentDidUpdate:
  useEffect(() => {
    startTimer();
    return  () => {
      clearInterval(timerRef.current);
      // console.info("====clearInterval-timerID===="+timerRef.current);
    };
  },
    [currentPage],
  );

  return (
    <View style={styles.container}>
      <ScrollView
        ref={scrollViewRef}
        horizontal={true}
        showsHorizontalScrollIndicator={false}
        pagingEnabled={true}
        //当一帧滚动结束
        onMomentumScrollEnd={event => onAnimationEnd(event)}
        //开始拖拽
        onScrollBeginDrag={onScrollBeginDrag}
        //停止拖拽
        onScrollEndDrag={onScrollEndDrag}>
        {renderAllImage()}
      </ScrollView>
      <View style={styles.pageViewStyle}>{renderPageCircle()}</View>
    </View>
  );

  function startTimer() {
    // console.info('--startTimer--');
    let imgCount = ImageData.data.length;
    //添加定时器  this.timer --->可以理解成一个隐式的全局变量
    timerRef.current = setInterval(()=>{
      let activePage = 0;
      if (currentPage + 1 >= imgCount) {
        // console.info('==='+(currentPage + 1));
        activePage = 0;
      } else {
        activePage = currentPage + 1;
        // console.info('----'+activePage);
      }
      setCurrentPage(activePage);
      let offsetX = activePage * width;
      scrollViewRef.current.scrollTo({x: offsetX, y: 0, animated: true});
    },duration);
    // console.info("====startTimer-timerID===="+timerRef.current);
  }
  //  当一帧滚动结束的时候调用
  function onAnimationEnd(event) {
    let offSetX = event.nativeEvent.contentOffset.x;
    let currentPage = Math.floor(offSetX / width);
    setCurrentPage(currentPage);
  }

  function onScrollBeginDrag() {
    // console.warn('开始拖拽');
    clearInterval(timerRef.current);
    // console.info("====onScrollBeginDrag-timerID===="+timerRef.current);
  }

  function onScrollEndDrag() {
    startTimer();
  }

  function renderAllImage() {
    let allImage = [];
    let imgsArr = ImageData.data;
    for (let i = 0; i < imgsArr.length; i++) {
      var imgItem = imgsArr[i];
      allImage.push(
        <Image key={i} source={{uri: imgItem.img}} style={{width: width, height: 120}}/>
      )
    }
    return allImage;
  }

  function renderPageCircle() {
    let indicatorArr = [];
    let style;
    let imgsArr = ImageData.data;
    for (let i = 0; i < imgsArr.length; i++) {
      // alert(i);
      // console.warn(i)
      style = (i === currentPage) ? {color:'orange'} : {color:'#ffffff'};
      indicatorArr.push(
        <Text key={i} style={[{fontSize: 25},style]}>&bull;</Text>
      )
    }
    return indicatorArr;
  }
};

const styles = StyleSheet.create({
  container: {
  },
  pageViewStyle: {
    width: width,
    height: 30,
    backgroundColor: 'rgba(0,0,0,0.4)',
    position: 'absolute',
    paddingRight: 15,
    bottom: 0,
    flexDirection: 'row',
    justifyContent: 'flex-end',
    alignItems: 'center',
  },
});
//输出类
module.exports = Banner;

ImageData.json

{
  "data": [
    {
      "img" : "img_01",
      "title" : "你那一笑倾国倾城"
    },
    {
      "img" : "img_02",
      "title" : "那里记录了最唯美的爱情故事"
    },
    {
      "img" : "img_03",
      "title" : "我怎么是一个剩女"
    },
    {
      "img" : "img_04",
      "title" : "生命中最后的四分钟"
    },
    {
      "img" : "img_05",
      "title" : "我们都需要治疗"
    }
  ]
}

Banner2.js(Class组件)

import React from "react";
import {
  ScrollView,
  StyleSheet,
  Text,
  View,
  Dimensions,
  Image,
} from 'react-native';

let {width} = Dimensions.get('window');
let ImageData = require('./ImageData.json');

class Banner2 extends React.Component {
  constructor() {
    super();
    this.state = {
      currentPage: 0,
    };
    this.duration = 2000;
    this.scrollViewRef = React.createRef();
    // 为了在回调中使用 `this`,这个绑定是必不可少的
    this.beginDrag = this.beginDrag.bind(this);
    this.endDrag = this.endDrag.bind(this);
  }

  componentDidMount() {
    this.startTimer();
  }

  componentWillUnmount() {
    this.timerID && clearInterval(this.timerID);
  }

  render(){
    return(
      <View style={styles.container}>
        <ScrollView
          ref={this.scrollViewRef}
          horizontal={true}
          showsHorizontalScrollIndicator={false}
          pagingEnabled={true}
          //开始拖拽
          onScrollBeginDrag={this.beginDrag}
          //停止拖拽
          onScrollEndDrag={this.endDrag}
          //当一帧滚动结束
          onMomentumScrollEnd={event => this.onAnimationEnd(event)}
        >
          {this.renderAllImage()}
        </ScrollView>
        <View style={styles.pageViewStyle}>{this.renderPageCircle()}</View>
      </View>
    );
  }

   startTimer() {
     const imgCount = ImageData.data.length;
     //添加定时器  this.timer --->可以理解成一个隐式的全局变量
     this.timerID = setInterval(()=>{
       let activePage;
       if (this.state.currentPage + 1 >= imgCount) {
         console.warn('==='+(this.state.currentPage + 1));
         activePage = 0;
       } else {
         activePage = this.state.currentPage + 1;
         console.warn('----'+activePage);
       }
       this.setState({currentPage:activePage});
       const offsetX = activePage * width;
       this.scrollViewRef.current && this.scrollViewRef.current.scrollTo({x: offsetX, y: 0, animated: true});
     },this.duration);
     console.info(this.timerID);
  }
  //开始拖拽
  beginDrag() {
    // console.warn('开始拖拽');
    this.timerID && clearInterval(this.timerID);
    console.info(this.timerID);
  }

  //结束拖拽
  endDrag() {
    // console.warn('结束拖拽')
    this.startTimer();
  }

  //  当一帧滚动结束的时候调用
  onAnimationEnd(event) {
    // console.warn('当一帧滚动结束的时候调用')
    const offSetX = event.nativeEvent.contentOffset.x;
    const currentPage = Math.floor(offSetX / width);
    this.setState({currentPage:currentPage});
  }

  renderAllImage() {
    let allImage = [];
    let imgsArr = ImageData.data;
    for (let i = 0; i < imgsArr.length; i++) {
      let imgItem = imgsArr[i];
      allImage.push(
        <Image key={i} source={{uri: imgItem.img}} style={{width: width, height: 150}}/>
      )
    }
    return allImage;
  }

  renderPageCircle() {
    let indicatorArr = [];
    let style;
    let imgsArr = ImageData.data;
    for (let i = 0; i < imgsArr.length; i++) {
      // alert(i);
      // console.warn(i)
      style = (i === this.state.currentPage) ? {color:'orange'} : {color:'#ffffff'};
      indicatorArr.push(
        <Text key={i} style={[{fontSize: 25},style]}>&bull;</Text>
      )
    }
    return indicatorArr;
  }
}

const styles = StyleSheet.create({
  container: {
  },
  pageViewStyle: {
    width: width,
    height: 30,
    backgroundColor: 'rgba(0,0,0,0.4)',
    position: 'absolute',
    bottom: 0,
    paddingRight: 15,
    flexDirection: 'row',
    justifyContent: 'flex-end',
    alignItems: 'center',
  },
});
//输出类
module.exports = Banner2;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值