React Native 小组件简单开发 - 不定时更新

一、顶部导航栏

1、index.js

index.js 引用自定义组件,通过props传递参数

import React, {Component} from 'react';
import TopNavigator from './TopNavigator';
import Game from './components/game';
import Music from './components/music';
import Video from './components/video';
import Main from './components/main';
import LiveStreaming from './components/liveStreaming';
import Recommend from './components/recommend';
import GhostAnimal from './components/ghostAnimal';
import Dance from './components/dance';
import BigData from './components/bigData';

export default class TopNavigationBar extends Component {
  render() {
    const navigationParams = {
      defaultOption: 'game',
      options: [
        {
          key: 'game',
          title: '游戏',
          selectColor: '#fe56a1',
          screen: Game,
        },
        {
          key: 'music',
          title: '音乐',
          selectColor: '#fe56a1',
          screen: Music,
        },
        {
          key: 'video',
          title: '影视',
          selectColor: '#fe56a1',
          screen: Video,
        },
        {
          key: 'main',
          title: '首页',
          selectColor: '#fe56a1',
          screen: Main,
        },
        {
          key: 'liveStreaming',
          title: '直播',
          selectColor: '#fe56a1',
          screen: LiveStreaming,
        },
        {
          key: 'recommend',
          title: '推荐',
          selectColor: '#fe56a1',
          screen: Recommend,
        },
        {
          key: 'ghostAnimal',
          title: '鬼畜',
          selectColor: '#fe56a1',
          screen: GhostAnimal,
        },
        {
          key: 'dance',
          title: '舞蹈',
          selectColor: '#fe56a1',
          screen: Dance,
        },
        {
          key: 'bigData',
          title: '大数据',
          selectColor: '#fe56a1',
          screen: BigData,
        },
      ],
    };
    return <TopNavigator {...navigationParams}></TopNavigator>;
  }
}

2、TopNavigator.js(主要实现)

Navigator.js 自定义导航栏组件

import React, {Component} from 'react';
import {
  Text,
  View,
  StyleSheet,
  TouchableOpacity,
  SafeAreaView,
  ScrollView,
  FlatList,
} from 'react-native';

export default class Navigation extends Component {
  static defaultProps = {
    defaultOption: '', // 默认页
    options: [], // 导航栏组件
  };
  state = {
    key: 'Main',
  };
  componentDidMount() {
    const {defaultOption} = this.props;
    defaultOption && this.checkPage(defaultOption);
  }
  // 切换页面
  checkPage = key => {
    this.setState({key});
  };
  render() {
    const {key} = this.state;
    const {options} = this.props;
    const cloumnList = ({item}) => (
      <TouchableOpacity
        onPress={() => this.checkPage(item.key)}
        style={
          item.key == key
            ? {...styles.selectBtn, borderColor: item.selectColor}
            : styles.btn
        }>
        <Text
          style={
            item.key == key
              ? {...styles.selectBtnTxt, color: item.selectColor}
              : styles.btnTxt
          }>
          {item.title}
        </Text>
      </TouchableOpacity>
    );
    return (
      <>
        {/* 导航栏 */}
        <SafeAreaView>
          <FlatList
            style={styles.btnContent}
            // 数据
            data={options}
            // 数据处理
            renderItem={cloumnList}
            // 每列的key
            keyExtractor={item => item.key}
            // 水平布局
            horizontal
            // 隐藏水平滚动条
            showsHorizontalScrollIndicator={false}
          />
        </SafeAreaView>
        {/* 视图 */}
        <SafeAreaView style={styles.box}>
          <ScrollView style={styles.viewContent}>
            <View style={{backgroundColor: '#f4f4f4'}}>
              {options
                .filter(item => item.key === key)
                .map(nav => React.createElement(nav.screen, {key: nav.key}))}
            </View>
          </ScrollView>
        </SafeAreaView>
      </>
    );
  }
}

const styles = StyleSheet.create({
  btnContent: {
    backgroundColor: '#fff',
  },
  btn: {
    // 上下内边距
    paddingVertical: 5,
    // 左右内边距
    paddingHorizontal: 5,
    // 左右外边距
    marginHorizontal: 10,
  },
  selectBtn: {
    paddingVertical: 5,
    paddingHorizontal: 5,
    marginHorizontal: 10,
    borderBottomWidth: 2,
  },
  btnTxt: {
    fontSize: 14,
  },
  selectBtnTxt: {
    fontSize: 15,
    fontWeight: 'bold',
  },
  viewContent: {
    padding: 5,
  },
  box: {
    flex: 1,
    backgroundColor: '#fff',
  },
});

3、最终效果图

最终效果图展示

在这里插入图片描述
在这里插入图片描述

二、底部导航栏

1、index.js

index.js 引用自定义组件,通过props传递参数

import React, {Component} from 'react';
import Main from './components/Main';
import Dynamic from './components/Dynamic';
import Shop from './components/Shop';
import Mine from './components/Mine';
import Navigator from './navigator';

export default class BottonNavifationBar extends Component {
  render() {
    const navigatorParams = {
      defaultPageKey: 'Main', // 默认页,使用的参数是key
      navigator: [
        {
          key: 'Main', // 页面标识
          title: '首页', // 导航栏名称
          icon: require('../../resource/main.png'), // 导航栏图片
          selectIcon: require('../../resource/main1.png'), // 导航栏选中时的图片
          color: '#000', // 文字颜色
          selectColor: '#fe56a1', // 导航栏选中时的文字颜色
          screen: Main, // 引用组件
        },
        {
          key: 'Dynamic',
          title: '动态',
          icon: require('../../resource/dynamic.png'),
          selectIcon: require('../../resource/dynamic1.png'),
          color: '#000',
          selectColor: '#fe56a1',
          screen: Dynamic,
        },
        {
          key: 'Shop',
          title: '商城',
          icon: require('../../resource/shop.png'),
          selectIcon: require('../../resource/shop1.png'),
          color: '#000',
          selectColor: '#fe56a1',
          screen: Shop,
        },
        {
          key: 'Mine',
          title: '我的',
          icon: require('../../resource/mine.png'),
          selectIcon: require('../../resource/mine1.png'),
          color: '#000',
          selectColor: '#fe56a1',
          screen: Mine,
        },
      ],
    };
    return <Navigator {...navigatorParams}></Navigator>;
  }
}

2、Navigator.js(主要实现)

Navigator.js 自定义导航栏组件,我是起名渣,参数名什么的就随便看看吧,我觉得样式还是挺关键的,不然都摆不出一个好看的页面

import React, {Component} from 'react';
import {
  Text,
  View,
  StyleSheet,
  TouchableOpacity,
  SafeAreaView,
  ScrollView,
  Image,
} from 'react-native';

export default class Navigator extends Component {
  static defaultProps = {
    defaultPageKey: '', // 默认页,使用的key参数
    navigator: [], // 导航栏数组
  };

  state = {
    key: 'Main',
  };

  componentDidMount() {
    this.checkNav(this.props.defaultPageKey);
  }

  // 切换页面
  checkNav = key => {
    // 设置默认页
    this.setState({key});
  };

  render() {
    const {key} = this.state;
    const {navigator} = this.props;

    return (
      <SafeAreaView style={{flex: 1}}>
        {/* 视图 */}
        <ScrollView style={styles.contentView}>
          <View style={styles.content}>
            {navigator
              .filter(item => item.key === key)
              .map(nav => React.createElement(nav.screen, {key: nav.key}))}
          </View>
        </ScrollView>
        {/* 导航栏 */}
        <View style={styles.navigationView}>
          {navigator.map(item => {
            return (
              <TouchableOpacity
                key={item.key}
                style={styles.navBtn}
                onPress={() => this.checkNav(item.key)}>
                <Image
                  source={item.key === key ? item.selectIcon : item.icon}
                  style={styles.btnImg}></Image>
                <Text
                  style={
                    item.key === key
                      ? {...styles.btnTxt, color: item.selectColor}
                      : {...styles.btnTxt, color: item.color}
                  }>
                  {item.title}
                </Text>
              </TouchableOpacity>
            );
          })}
        </View>
      </SafeAreaView>
    );
  }
}

// 样式
const styles = StyleSheet.create({
  contentView: {
    backgroundColor: '#fff',
    padding: 10,
  },
  content: {
    flex: 1,
    backgroundColor: '#f4f4f4',
  },
  navigationView: {
    backgroundColor: '#fff',
    padding: 10,
    flexDirection: 'row',
    justifyContent: 'space-around',
    borderTopWidth: 2,
    borderColor: '#f4f4f4',
  },
  navBtn: {
    padding: 20,
  },
  btnImg: {
    width: 35,
    height: 35,
  },
  btnTxt: {
    fontSize: 12,
    textAlign: 'center',
  },
  text: {
    fontSize: 42,
  },
});

3、最终效果图

最终效果图展示 ,顶上的那个标题是我写的路由组件,我把自己的东西都集成在一个地方了,所以这个大家就不用在意了

在这里插入图片描述
在这里插入图片描述

三、轮播图

1、index.js

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

// 引入Dimensions库 - 获取设备宽高
var {width, height} = Dimensions.get('window');

// 这个可以从 接口 或 json文件 获取
const imageData = {
  data: [
    {
      img: require('../../resource/carousel1.jpeg'),
      title: '图片一',
    },
    {
      img: require('../../resource/carousel2.jpeg'),
      title: '图片二',
    },
    {
      img: require('../../resource/carousel3.jpeg'),
      title: '图片三',
    },
  ],
  other: [
    {
      title: '其他信息',
    },
  ],
};

export default class Carousel extends Component {
  state = {
    currentPage: 0,
  };
  // 定时器
  timer = undefined;

  componentDidMount() {
    // 加载完毕时开始自动轮播
    this.autoPlay();
  }

  componentWillUnmount() {
    // 组件销毁时清除定时器
    this.stopPlay();
  }

  // scrollView子视图
  renderItem() {
    // 根据json数据实例化视图
    let itemAry = imageData.data.map((item, index) => (
      <Image key={index} style={styles.itemStyle} source={item.img} />
    ));
    return itemAry;
  }

  // 分页指示器
  renderPagingIndicator() {
    const {currentPage} = this.state;

    let itemAry = imageData.data.map((item, index) => {
      let autoColor =
        currentPage == index ? {color: '#fff'} : {color: '#a3a9b9'};
      return (
        <Text key={index} style={[{fontSize: 30}, autoColor]}></Text>
      );
    });
    return itemAry;
  }

  // 监听滚动
  onAnimationEnd(e) {
    // 求出水平方向上的偏移量
    let offSetX = e.nativeEvent.contentOffset.x;
    // 计算当前页码
    let currentPage = parseInt((offSetX / width).toFixed(0));
    this.stopPlay();
    // 重新绘制UI
    this.setState({currentPage}, () => this.autoPlay());
  }

  // 切换轮播
  checkCarousel = () => {
    let {currentPage} = this.state;
    if (currentPage + 1 >= imageData.data.length) {
      currentPage = 0;
    } else {
      currentPage++;
    }
    // console.log(currentPage);
    this.scrollView && this.scrollView.scrollTo({x: width * currentPage});
    this.setState({currentPage});
  };

  // 自动轮播
  autoPlay = () => (this.timer = setInterval(() => this.checkCarousel(), 3000));

  // 停止轮播 / 清除定时器
  stopPlay = () => this.timer && clearInterval(this.timer);

  render() {
    const {currentPage} = this.state;
    return (
      <>
        <View style={styles.container}>
          <ScrollView
            ref={ref => (this.scrollView = ref)}
            style={styles.scrollViewStyle}
            horizontal={true} // 水平方向 展示
            showsHorizontalScrollIndicator={false} // 隐藏水平指示器
            showsVerticalScrollIndicator={false} // 隐藏垂直指示器
            pagingEnabled={true} // 开启分页功能
            onMomentumScrollEnd={e => this.onAnimationEnd(e)} // 当一帧滚动完毕的时候调用
          >
            {this.renderItem()}
          </ScrollView>
          {/* 实例化分页指示器 */}
          <View style={styles.pagingIndicatorStyle}>
            {this.renderPagingIndicator()}
          </View>
        </View>
        <View>
          <Text>这是图片_{currentPage + 1}</Text>
        </View>
      </>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    backgroundColor: '#fff',
  },
  scrollViewStyle: {
    // 背景色
    backgroundColor: 'black',
    // 上边距
    marginTop: 20,
  },
  itemStyle: {
    // 尺寸
    width: width,
    height: 200,
    // 图片等比例拉伸
    resizeMode: 'contain',
  },
  pagingIndicatorStyle: {
    // 背景色(使背景色为全透明)
    backgroundColor: 'rgba(255,255,255,0.0)',
    // 尺寸
    width: width,
    // 主轴方向与对齐方式
    flexDirection: 'row',
    justifyContent: 'center',
    // 绝对定位,使页码指示器盖在scrollView上面
    position: 'absolute',
    bottom: 0,
    left: width / 3,
  },
});


2、效果图展示

在这里插入图片描述

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值