zoukankan      html  css  js  c++  java
  • 【水滴石穿】react-native-app

    项目地址:https://github.com/WQone/react-native-app
    这个是一个非常优秀的小姐姐写的,希望大家能够以她为榜样,一起加油进步呀~
    先看效果
    分析package.json可以发现其实没有遇到很多很特别的组件


    还是先来分析代码

    //index.js
    /**
     * @format
     */
    
    import {AppRegistry} from 'react-native';
    import App from './App';
    import {name as appName} from './app.json';
    
    AppRegistry.registerComponent(appName, () => App);
    
    
    //app.js
    //主要定义的是routter
    import router from './src/router/index'
    
    //导航注册
    export default router;
    
    
    //index.js
    import React from 'react';
    import {
      createStackNavigator,
      createAppContainer,
      createBottomTabNavigator,
      createSwitchNavigator,
    } from 'react-navigation';
    import Ionicons from 'react-native-vector-icons/Ionicons';
    
    import Login from '../views/Login/index';
    import Home from '../views/Home/index';
    import Mine from '../views/Mine/index';
    
    const BottomNavigator = createBottomTabNavigator(
      {
        Home: {
          screen: Home,
          navigationOptions: {
            title: '首页',
            tabBarIcon: ({ focused, horizontal, tintColor }) => {
              return <Ionicons name={'ios-home'} size={25} style={{ color: tintColor }} />;
            },
          },
        },
        Mine: {
          screen: Mine,
          navigationOptions: {
            title: '我的',
            tabBarIcon: ({ focused, horizontal, tintColor }) => {
              return <Ionicons name={'logo-octocat'} size={25} style={{ color: tintColor }} />;
            },
          },
        },
      },
      {
        tabBarOptions: {
          activeTintColor: '#168f48',
        },
      },
    );
    
    const AppNavigator = createStackNavigator(
      {
        Home: {
          screen: BottomNavigator,
          navigationOptions: () => ({
            title: '首页',
            headerBackTitle: null,
          }),
        },
      },
      {
        headerMode: 'none',
      },
    );
    
    const LoginNavigator = createStackNavigator(
      {
        Login: {
          screen: Login,
          navigationOptions: () => ({
            title: '登录',
            headerBackTitle: null,
          }),
        },
      },
      {
        headerMode: 'none',
        // navigationOptions: {
        //   headerStyle: {
        //     backgroundColor: '#f4511e',
        //   },
        //   headerTintColor: '#fff',
        //   headerTitleStyle: {
        //     fontWeight: 'bold',
        //   },
        // },
        // headerLayoutPreset: 'center',
      },
    );
    //路由定义了初始化显示页面
    const App = createSwitchNavigator(
      {
        LoginNavigator,
        AppNavigator,
      },
      {
        initialRouteName: 'LoginNavigator',
      },
    );
    
    //导航注册
    export default createAppContainer(App);
    
    
    //src/utils/constance.js
    //对设备类型进行了判断
    /**
     * 常量
     */
    
    import { Dimensions, Platform } from 'react-native';
    
    const { height, width } = Dimensions.get('window');
    
    export const VALUE = {
       width,
      height: height,
      ios: Platform.OS === 'ios',
      android: Platform.OS === 'android',
    };
    
    //src/views/Login/index.js
    import React, { Component } from 'react';
    import {
      StatusBar,
      StyleSheet,
      Image,
      TouchableOpacity,
      Button,
      View,
      Text,
      TextInput,
    } from 'react-native';
    import SimpleLineIcons from 'react-native-vector-icons/SimpleLineIcons';
    import { VALUE } from '../../utils/constance';
    
    export default class Login extends Component {
      constructor(props) {
        super(props);
        this.state = { user_text: '', pass_text: '' };
      }
      onPressButton = () => {
        //跳转到home页面
        this.props.navigation.navigate('Home');
      };
      render() {
        return (
          <View style={styles.container}>
            <StatusBar backgroundColor="transparent" translucent barStyle={'dark-content'} />
            <Image
              source={require('../../assets/images/loginbg.jpeg')}
              style={styles.loginBg}
              resizeMode="stretch"
            />
            <View style={styles.login}>
              <View style={styles.InputName}>
                <SimpleLineIcons name={'user'} size={21} style={{ lineHeight: 40, color: 'white' }} />
                <TextInput
                  onChangeText={(user_text) => this.setState({ user_text })}
                  style={styles.Input}
                  autoComplete={'username'}
                  underlineColorAndroid={'transparent'}
                  maxLength={30}
                  placeholder={'请输入用户名'}
                  placeholderTextColor={'white'}
                />
              </View>
              <View style={styles.InputPass}>
                <SimpleLineIcons name={'lock'} size={23} style={{ lineHeight: 40, color: 'white' }} />
                <TextInput
                  onChangeText={(pass_text) => this.setState({ pass_text })}
                  style={styles.Input}
                  autoComplete={'password'}
                  secureTextEntry={true}
                  underlineColorAndroid={'transparent'}
                  maxLength={16}
                  placeholder={'请输入密码'}
                  placeholderTextColor={'white'}
                />
              </View>
              <TouchableOpacity
                activeOpacity={0.9} //点击时的透明度
                style={styles.InputBtn}
                //点击事件,要记得绑定
                onPress={this.onPressButton}
              >
                <Text style={{ fontSize: 16, color: '#168f48', fontWeight: 'bold' }}>立即登录</Text>
              </TouchableOpacity>
            </View>
          </View>
        );
      }
    }
    
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: '#f5f5f5',
        fontSize: 19,
      },
      loginBg: {
         VALUE.width,
        height: VALUE.height,
        justifyContent: 'center',
        alignItems: 'center',
        position: 'absolute',
        zIndex: -1,
      },
      login: {
        paddingLeft: 30,
        paddingRight: 30,
        flexDirection: 'column',
        alignItems: 'center',
        justifyContent: 'center',
         VALUE.width,
        height: VALUE.height,
      },
      InputName: {
        flexDirection: 'row',
        height: 45,
        borderColor: 'white',
        borderBottomWidth: 1,
        marginBottom: 20,
         '100%',
        paddingBottom: 5,
      },
      InputPass: {
        flexDirection: 'row',
        height: 45,
        borderColor: 'white',
        borderBottomWidth: 1,
         '100%',
        paddingBottom: 5,
      },
      Input: {
        fontSize: 16,
        padding: 0,
        paddingLeft: 20,
        // color: 'white',
      },
      InputBtn: {
        marginTop: 30,
         '100%',
        height: 47,
        backgroundColor: 'white',
        justifyContent: 'center',
        alignItems: 'center', //显示Text组件居中
        borderRadius: 4, //按钮圆角
        alignSelf: 'center',
      },
    });
    

    看点击登陆之后进入home页面效果

    有封装轮播哟

    //src/views/Home/index.js
    import React, { Component } from 'react';
    import { ScrollView, StyleSheet, Button, Text, View, Image } from 'react-native';
    import { VALUE } from '../../utils/constance';
    import PageScrollView from '../../components/PageScrollView';
    import mockjsInit from '../../api/mock'; // 添加mockjs拦截请求,模拟返回服务器数据
    import api from '../../api/page';
    
    export default class Home extends Component {
      constructor(props) {
        super(props);
        this.state = {
          value: '1212',
          imageUrl: [
            {
              uri:
                'https://images.pexels.com/photos/2176338/pexels-photo-2176338.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
            },
            {
              uri:
                'https://images.pexels.com/photos/2209511/pexels-photo-2209511.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
            },
            {
              uri:
                'https://images.pexels.com/photos/2236703/pexels-photo-2236703.jpeg?auto=compress&cs=tinysrgb&dpr=1&w=500',
            },
          ],
        };
      }
      componentDidMount() {
        // mockjsInit();
      }
      onPressButton = () => {
        this.setState({
          value: JSON.stringify(5656),
        });
        api
          .list()
          .then((res) => {
            this.setState({
              value: JSON.stringify(777),
            });
          })
          .catch((error) => {
            alert(error.message);
          });
      };
      render() {
        return (
          <View style={styles.container}>
            <PageScrollView
              style={{  VALUE.width, height: 210 }}
              imageArr={this.state.imageUrl}
              infiniteInterval={5000}
              pointerColor={['#fff', '#0000', '#fff']}
              pointerViewStyle={{ bottom: 10 }}
            />
            <Text onPress={this.onPressButton}>{this.state.value}</Text>
          </View>
        );
      }
    }
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: '#f2f2f2',
        fontSize: 19,
      },
      scrollStyle: {
        height: 210,
         VALUE.width,
      },
    });
    

    看封装的轮播代码

    //src/components/PageScrollView.js
    import React, { Component } from 'react';
    import {
      View,
      ScrollView,
      Platform,
      Dimensions,
      InteractionManager,
      Image,
      TouchableOpacity,
      ImageBackground,
    } from 'react-native';
    
    const {  w, height: h } = Dimensions.get('window');
    
    class PageScrollView extends Component {
      constructor(props) {
        super(props);
        this.initState();
      }
    
      //初始化state的值
      initState = () => {
        this.state = {
          //当前滚动到哪一页
          currentPage: 0,
          //整数形式的currentPage
          intCP: -1,
          //总共有几页
          pageNum: this.props.imageArr.length || this.props.datas.length,
    
          //记录当前是否为手指拖拽
          ifTouch: false,
          // 当onScroll水平滚动时的滚动大小(x值)的数组
          scrollXArr: [],
          // 当onScroll垂直滚动时的滚动大小(x值)的数组
          scrollYArr: [],
    
          //scrollView是否可以滚动
          scrollEnabled: true,
    
          //ScrollView自身View的宽高
          viewHeight: 0,
          viewWidth: 0,
           0,
          height: 0,
          //记录是否是首次
          ifFirst: true,
        };
      };
    
      static defaultProps = {
        //使用官方提供的哪一个内置样式
        builtinStyle: null,
        //使用内置样式时用户自定义的图片宽高
        builtinWH: {},
    
        //设置整个组件View的style样式
        style: {},
    
        //轮播图片的数组(该数组存在时使用该数组,datas数组失效)
        imageArr: [],
        //如果是传入图片数组时,自定义的图片样式(该属性在自定义View时无用)
        imageStyle: null,
    
        // ccStyle:null,
    
        //自定义view中对应的数据数组
        datas: [],
        //每一个自定义View的具体渲染
        view: () => {},
    
        //每一个View的宽高(当滚动到当前这个View时的宽高,用于View的宽高会随滚动改变时才用){宽度,height:高度}
        // contentWH:null,
    
        //速度大于多少时为有向左(右,上,下)翻一页的意图(数值越大,要滑动速度越快(越难)才能到下一页,数值越小,滑动越慢(越容易)可以到下一页,)
        goToNextPageSpeed: 3,
    
        //水平还是竖直方向的ScrollView
        HorV: 'h',
    
        //是否无限轮播(无限滚动)
        ifInfinite: true,
        //是否自动轮播
        ifAutoScroll: true,
        //自动轮播每张切换的时长(毫秒)
        infiniteInterval: 2000,
        //图片的显示形式
        resizeMode: 'cover',
        //点击图片时执行的操作(不是自定义View的时候)
        dealWithClickImage: null,
    
        //在当前滚动到的页面改变时调用的方法
        currentPageChangeFunc: null,
    
        //是否允许用户手动滚动ScrollView
        scrollEnabled: true,
        //组件加载好后,并且布局好得到相应宽高后的执行的操作
        didMount: null,
    
        //当滚动到当前页的大小为正常大小的多大
        // sizeLarge:1,
        //自定义View时滚动到旁边时的大小为正常大小的多大
        sizeSmall: null,
        //自定义View时滚动到旁边时的透明度
        opacitySmall: null,
        //自定义View时滚动到旁边时旋转的角度
        rotateDeg: null,
        //自定义View时滚动到旁边时的图片的倾斜角度
        skewDeg: null,
    
        //是否显示当前图片指示器View(下面的点)
        ifShowPointerView: true,
        //指示器的的相关颜色.分别为:当前页的颜色,其他页的颜色,边框的颜色
        pointerColor: ['#fff', '#0000', '#fff'],
        //自定义指示器View的样式(绝对定位的top,bottom...)
        pointerViewStyle: null,
        //自定义指示器圆点的样式(圆点大小)
        pointerStyle: null,
        //自定义指示器View
        renderPointerView: null,
      };
    
      //官方设置的内置样式的各个参数
      builtinStyleArgs = {
        sizeChangeMode: { sS: 0.7, oS: 0.7, bg: '#999' },
        rotateChangeMode: { rS: 45, skewS: 45, oS: 0.5, sS: 0.5, bg: '#999' },
      };
      //官方设置的内置样式
      builtinStyles = {
        sizeChangeMode: (index, data, { size, opacity }) => {
          let { viewWidth, viewHeight } = this.state;
          let { HorV, builtinWH } = this.props;
          let isH = HorV === 'h';
          let customW = null,
            customH = null;
          if (builtinWH) {
            customW = builtinWH.width;
            customH = builtinWH.height;
          }
          let widimage = customW || w * 0.6,
            wid = isH ? widimage : viewWidth,
            hei = isH ? viewHeight : customH || (widimage / 16) * 9,
            heimage = customH || (widimage / 16) * 9;
          return (
            <View
              style={[
                {
                   wid,
                  height: hei,
                  alignItems: 'center',
                  justifyContent: 'center',
                  backgroundColor: '#999',
                  opacity: opacity,
                },
              ]}
              onLayout={this.contentLayout}
            >
              <Image source={data} style={{  widimage * size, height: heimage * size }} />
            </View>
          );
        },
        rotateChangeMode: (index, data, { rotate, opacity, size }) => {
          let isios = Platform.OS === 'ios';
          let { rS, sS } = this.builtinStyleArgs['rotateChangeMode'];
          let { viewWidth, viewHeight } = this.state;
          let { HorV, builtinWH } = this.props;
          let Image = ImageBackground || Image;
          let isH = HorV === 'h';
          let customW = null,
            customH = null;
          if (builtinWH) {
            customW = builtinWH.width;
            customH = builtinWH.height;
          }
          let widimage = customW || (isH ? w * 0.5 : w * 0.7),
            wid1 = isH ? widimage : viewWidth,
            hei1 = isH ? viewHeight : customH || (widimage / 16) * 9,
            heimage = customH || (widimage / 16) * 9,
            hei = hei1,
            wid = wid1;
    
          let LH = hei,
            LW = wid;
          if (isH) {
            rotate ? (wid = Math.cos(Math.PI * (rotate / 180)) * wid1 * size) : (wid = wid1);
          } else {
            rotate ? (hei = Math.cos(Math.PI * (rotate / 180)) * hei1 * size) : (hei = hei1);
          }
          let SH = Math.cos(Math.PI * (rS / 180)) * hei1 * sS,
            SW = Math.cos(Math.PI * (rS / 180)) * wid1 * sS;
          return (
            <View
              style={[
                {
                   wid,
                  height: hei,
                  alignItems: 'center',
                  justifyContent: 'center',
                  backgroundColor: '#999',
                  opacity: opacity,
                  transform: [
                    isH ? { rotateY: rotate + 'deg' } : { rotateX: rotate + 'deg' },
                    isH
                      ? { skewY: rotate + 'deg' }
                      : isios
                      ? { skewX: rotate + 'deg' }
                      : { skewY: -rotate + 'deg' },
                  ],
                },
              ]}
              onLayout={(e) => {
                !this.distance && this.setDistance1(null, LW, LH, SW, SH);
              }}
            >
              <Image source={data} style={{  widimage * size, height: heimage * size }}>
                <View
                  style={{
                    position: 'absolute',
                    top: 0,
                    left: 0,
                    right: 0,
                    bottom: 0,
                    backgroundColor: '#000',
                    opacity: 1 - opacity,
                  }}
                />
              </Image>
            </View>
          );
        },
      };
    
      render() {
        let { style, builtinStyle } = this.props;
        let { builtinStyles, builtinStyleArgs } = this;
        return (
          <View
            style={[
              style || { flex: 1 },
              builtinStyle && { backgroundColor: builtinStyleArgs[builtinStyle].bg },
            ]}
            onLayout={this.viewOnLayout}
          >
            <ScrollView
              // 设置引用名称,让下面可以引用到
              ref={(ps) => {
                this.scrollView = ps;
              }}
              style={{ flex: 1 }}
              scrollEnabled={this.props.scrollEnabled && this.state.scrollEnabled}
              // 是否是水平的scrollView(默认为水平方向的)
              horizontal={this.props.HorV === 'h'}
              // 是否显示水平方向的滚动条
              showsHorizontalScrollIndicator={false}
              // 是否显示竖方向的滚动条
              showsVerticalScrollIndicator={false}
              // 开始拖拽
              onScrollBeginDrag={this.onScrollBeginDrag}
              // 停止拖拽
              onScrollEndDrag={this.onScrollEndDrag}
              onScroll={(e) => this.onScroll(e)}
              //多少毫秒触发一次上面的onScroll方法
              scrollEventThrottle={20}
              onLayout={this.scrollViewOnLayout}
            >
              {/*渲染scrollView*/}
              {this.renderScrollView()}
            </ScrollView>
            {/*渲染下面的指示器*/}
            {this.props.ifShowPointerView && this.renderPointer()}
          </View>
        );
      }
    
      //view加载好之后
      viewOnLayout = () => {
        this.state.ifFirst && this.props.didMount && this.props.didMount();
        this.state.ifFirst && (this.state.ifFirst = false);
      };
    
      //scrollView加载好后,自身的尺寸
      scrollViewOnLayout = (event) => {
        let { width, height } = event.nativeEvent.layout;
        this.setState({ viewHeight: height, viewWidth: width }, () => {});
      };
    
      //图片加载好后的尺寸
      imageLayout = (event) => {
        this.getContentStyle(event);
      };
    
      //每个分页view加载好后的尺寸
      contentLayout = (event) => {
        this.getContentStyle(event);
      };
    
      //获得每一页内容的样式(宽高)
      getContentStyle = (event) => {
        if (this.distance) {
          return;
        }
        let { width, height } = event.nativeEvent.layout;
        this.setDistance(width, height);
      };
      //设置this.state的宽高和distance
      setDistance = (width, height) => {
        if (this.distance) {
          return;
        }
        let isH = this.props.HorV === 'h';
        this.setState({  width, height: height }, () => {
          this.distance = isH ? this.state.width : this.state.height;
        });
      };
      //设置this.state的宽高和distance(有旋转,缩放时,即当前滚动到的图片与旁边的图片大小不一样时)
      setDistance1 = (event, LargeWidth, LargeHeight, SmallWidth, SmallHeight) => {
        if (this.distance) {
          return;
        }
        let isH = this.props.HorV === 'h';
        if (event) {
          let { width, height } = event.nativeEvent.layout;
          this.setDistance(width, height);
        } else {
          this.setState({  LargeWidth, height: LargeHeight }, () => {
            this.distance = isH ? SmallWidth : SmallHeight;
          });
        }
      };
    
      //渲染下面的指示器
      renderPointer = () => {
        let { pointerColor: pc, renderPointView } = this.props;
        let viewArr = [];
        let currentPage = this.getintCP();
    
        let datas = this.props.imageArr.length ? this.props.imageArr : this.props.datas;
        for (let i = 0; i < datas.length; i++) {
          let selected = i === currentPage;
          viewArr.push(
            renderPointView ? (
              <View key={i}>{renderPointView(selected)}</View>
            ) : (
              <View
                key={i}
                style={[
                  {  8, height: 8, borderRadius: 4, borderColor: pc[2], borderWidth: 1 },
                  i && { marginLeft: 10 },
                  selected ? { backgroundColor: pc[0] } : { backgroundColor: pc[1] },
                  this.props.pointerStyle,
                ]}
              />
            ),
          );
        }
        return (
          <View
            style={[
              {
                position: 'absolute',
                bottom: this.state.viewHeight / 10,
                flexDirection: 'row',
                 this.state.viewWidth,
                justifyContent: 'center',
              },
              this.props.pointerViewStyle,
            ]}
          >
            {viewArr}
          </View>
        );
      };
    
      //获得整数型的当前滚动页面
      getintCP() {
        let currentPage = Math.round(this.state.currentPage);
        let ifInfinite = this.props.ifInfinite;
        ifInfinite && (currentPage %= this.state.pageNum);
        return currentPage;
      }
      //获得整数型滚动页面后的操作
      dealWithIntCP() {
        let currentPage = this.getintCP();
        if (currentPage !== this.state.intCP) {
          this.props.currentPageChangeFunc && this.props.currentPageChangeFunc(currentPage);
          this.state.intCP = currentPage;
        }
      }
    
      // 渲染scrollView
      renderScrollView = () => {
        let {
          imageArr,
          datas,
          ifInfinite,
          dealWithClickImage: dealClick,
          sizeSmall,
          opacitySmall,
          rotateDeg,
          skewDeg,
          imageStyle,
          resizeMode,
          HorV,
          builtinStyle,
        } = this.props;
        let { viewWidth, width, viewHeight, height, pageNum, currentPage } = this.state;
        let { builtinStyles, builtinStyleArgs } = this;
        this.dealWithIntCP();
        //datas数据
        datas = imageArr.length ? imageArr : datas;
        ifInfinite && (datas = [...datas, ...datas, ...datas]);
        //当滚动到当前页的大小为正常大小的多大
        let sL = 1;
        //当滚动到旁边时的大小为正常大小的多大
        let sS = sizeSmall;
        // let sS=0.5;
        let oL = 1;
        //滚到旁边时的透明度
        let oS = opacitySmall;
        //滚动到旁边时的旋转角度
        let rS = rotateDeg;
        //滚动到旁边时的倾斜角度
        let skewS = skewDeg;
        if (builtinStyle) {
          let args = builtinStyleArgs[builtinStyle];
          ({ sS, oS, rS, skewS } = args);
        }
        let arr = [];
        if (HorV === 'h') {
          //当滚动到第一张时的左边空白部分
          arr.push(
            <View
              key={-2}
              style={{  (viewWidth - width) / 2, height: viewHeight, backgroundColor: '#0000' }}
            />,
          );
        } else {
          //竖直ScrollView时
          arr.push(
            <View
              key={-2}
              style={{  viewWidth, height: (viewHeight - height) / 2, backgroundColor: '#0000' }}
            />,
          );
        }
    
        for (let i = 0; i < datas.length; i++) {
          let size = 1;
          let opacity = 1;
          let rotate = 0;
          let skew = 0;
          let distance;
          if (sS || oS || rS || skewS) {
            distance = Math.abs(currentPage - i);
            if (distance >= 1) {
              size = sS;
              opacity = oS;
              rotate = rS;
              skew = skewS;
            } else {
              size = sL - distance * (sL - sS);
              opacity = oL - distance * (oL - oS);
              rotate = distance * rS;
              skew = distance * skewS;
            }
          }
          if (this.props.imageArr.length) {
            let style = imageStyle || {  viewWidth, height: viewHeight };
            if (builtinStyle) {
              arr.push(
                <TouchableOpacity
                  activeOpacity={dealClick ? 0.5 : 1}
                  onPress={() => {
                    dealClick && dealClick(i % this.pNum);
                  }}
                  key={i}
                  style={[]}
                >
                  {/*<TouchableOpacity activeOpacity={dealClick?0.5:1} onPress={()=>{dealClick&&dealClick(i%this.pNum)}} key={i} style={[]} onLayout={this.contentLayout}>*/}
                  {builtinStyles[builtinStyle](i % pageNum, datas[i % pageNum], {
                    size,
                    opacity,
                    rotate,
                    skew,
                  })}
                </TouchableOpacity>,
              );
            } else {
              arr.push(
                <TouchableOpacity
                  activeOpacity={dealClick ? 0.5 : 1}
                  onPress={() => {
                    dealClick && dealClick(i % this.pNum);
                  }}
                  key={i}
                  style={style}
                  onLayout={this.imageLayout}
                >
                  <Image source={datas[i]} style={[style, { resizeMode: resizeMode }]} />
                </TouchableOpacity>,
              );
            }
          } else {
            arr.push(
              <View
                key={i}
                style={[]}
                onLayout={(event) => {
                  sS || oS || rS || skewS ? this.setDistance1(event) : this.contentLayout(event);
                }}
              >
                {sS || oS || rS || skewS
                  ? this.props.view(i % pageNum, datas[i % pageNum], { size, opacity, rotate, skew })
                  : this.props.view(i % pageNum, datas[i % pageNum])}
              </View>,
            );
          }
        }
        if (HorV === 'h') {
          //当滚动到最后一张时的右边的空白部分
          arr.push(
            <View
              key={-3}
              style={{  (viewWidth - width) / 2, height: viewHeight, backgroundColor: '#0000' }}
            />,
          );
        } else {
          //竖直方向
          arr.push(
            <View
              key={-3}
              style={{  viewWidth, height: (viewHeight - height) / 2, backgroundColor: '#0000' }}
            />,
          );
        }
        return arr;
      };
    
      //开始拖拽
      onScrollBeginDrag = (e) => {
        this.state.ifTouch = true;
        this.state.scrollXArr = [];
        this.state.scrollYArr = [];
        this.stopInfiniteInterval();
      };
      // 停止拖拽(升级后2)
      onScrollEndDrag = (e) => {
        this.state.ifTouch = false;
    
        this.props.ifInfinite && this.setState({ scrollEnabled: false });
        let speed = this.props.goToNextPageSpeed;
        let contentOffset = this.isH ? e.nativeEvent.contentOffset.x : e.nativeEvent.contentOffset.y;
        let scrollArr = this.isH ? this.state.scrollXArr : this.state.scrollYArr;
        let speed1 = scrollArr[scrollArr.length - 1] - scrollArr[scrollArr.length - 2];
        let speed2 = scrollArr[scrollArr.length - 2] - scrollArr[scrollArr.length - 3];
        let speed3 = scrollArr[scrollArr.length - 3] - scrollArr[scrollArr.length - 4];
        let speed4 = scrollArr[scrollArr.length - 1] - scrollArr[0];
        let currentPage;
        if (Math.abs(speed1) > speed || Math.abs(speed2) > speed || Math.abs(speed3) > speed) {
          // 速度(speed1,2,3)绝对值大于设定值时为有向左(右,上,下)翻一页的意图
          //speed4>0向右(上)翻(想去(下)(右)一页的意图)
          //speed4<0向左(下)翻(想去(上)(左)一页的意图)
          currentPage =
            speed4 > 0
              ? Math.ceil(contentOffset / this.distance)
              : Math.floor(contentOffset / this.distance);
        } else {
          currentPage = Math.round(contentOffset / this.distance);
        }
        //滚动到相应的界面
        this.scrollToPage(currentPage);
        //如果设置了自动轮播,则重新开启定时器
        this.props.ifAutoScroll && this.setInfiniteInterval();
      };
    
      // 当滚动scrollView的时候(升级后)
      onScroll = (e) => {
        let scrollPage;
        if (this.isH) {
          // scrollView当前滚动的数值
          this.state.scrollXArr.push(e.nativeEvent.contentOffset.x);
          scrollPage = e.nativeEvent.contentOffset.x / this.distance;
        } else {
          // scrollView当前滚动的数值
          this.state.scrollYArr.push(e.nativeEvent.contentOffset.y);
          scrollPage = e.nativeEvent.contentOffset.y / this.distance;
        }
        if (
          this.props.ifInfinite &&
          Math.abs(scrollPage - Math.ceil(scrollPage)) < 0.1 &&
          !this.state.ifTouch
        ) {
          //处理无限轮播,自动轮播滚动时的情况
          setTimeout(() => {
            this.infiniteScroll(Math.ceil(scrollPage));
          }, 200);
        } else {
          this.setState({ currentPage: scrollPage });
        }
      };
    
      //无限轮播时对滚动的处理
      infiniteScroll = (currentPage) => {
        if (currentPage < this.pNum || currentPage >= this.pNum * 2) {
          currentPage = (currentPage % this.pNum) + this.pNum;
          this.scrollToPage(currentPage, false);
        }
        //更新状态机
        this.setState({
          //当前页码
          currentPage: currentPage,
          scrollEnabled: true,
        });
      };
    
      //根据传入的要滚动到的页面数,滚动到相应的页面
      scrollToPage = (currentPage, animated = true) => {
        let pageNum = this.props.ifInfinite ? this.pNum * 3 : this.pNum;
        if (currentPage > pageNum - 1) {
          currentPage = pageNum - 1;
        }
        if (currentPage < 0) {
          currentPage = 0;
        }
        try {
          this.isH
            ? this.scrollView.scrollTo({ x: currentPage * this.distance, animated: animated })
            : this.scrollView.scrollTo({ y: currentPage * this.distance, animated: animated });
        } catch (e) {}
      };
    
      //父组件中使用ref手动滚动的方法
      manualScrollToPage = (currentPage, animated = true) => {
        if (this.props.ifInfinite && animated) {
          currentPage < this.pNum && (currentPage += this.pNum);
          currentPage >= this.pNum * 2 && (currentPage -= this.pNum);
        } else {
          if (currentPage > this.pNum - 1) {
            currentPage = this.pNum - 1;
          }
          if (currentPage < 0) {
            currentPage = 0;
          }
        }
        this.isH
          ? this.scrollView.scrollTo({ x: currentPage * this.distance, animated: animated })
          : this.scrollView.scrollTo({ y: currentPage * this.distance, animated: animated });
      };
    
      //设置轮播的定时器
      setInfiniteInterval = () => {
        let interval = this.props.infiniteInterval < 1000 ? 1000 : this.props.infiniteInterval;
        this.timer = setInterval(() => {
          let currentPage = Math.round(this.state.currentPage + 1);
          !this.props.ifInfinite && currentPage >= this.pNum && (currentPage = 0);
          this.scrollToPage(currentPage);
        }, interval);
      };
      //清除轮播定时器
      stopInfiniteInterval = () => {
        this.timer && clearInterval(this.timer);
      };
    
      componentDidMount() {
        this.isH = this.props.HorV === 'h';
        this.pNum = this.state.pageNum;
        this.props.ifAutoScroll && this.setInfiniteInterval();
      }
    
      didMount = () => {
        if (this.props.ifInfinite) {
          let isH = this.props.HorV === 'h';
          if (Platform.OS !== 'ios') {
            InteractionManager.runAfterInteractions(() => {
              this.scrollView.scrollTo(
                isH
                  ? { x: this.state.pageNum * this.distance, animated: false }
                  : { y: this.state.pageNum * this.distance, animated: false },
              );
            });
          } else {
            this.scrollView.scrollTo(
              isH
                ? { x: this.state.pageNum * this.distance, animated: false }
                : { y: this.state.pageNum * this.distance, animated: false },
            );
          }
        }
      };
    
      componentWillUpdate() {}
    
      componentWillUnmount() {
        this.stopInfiniteInterval();
      }
    }
    
    //输出组件类
    export default PageScrollView;
    

    固定了底部

    ///src/router/index.js
    import React from 'react';
    import {
      createStackNavigator,
      createAppContainer,
      createBottomTabNavigator,
      createSwitchNavigator,
    } from 'react-navigation';
    import Ionicons from 'react-native-vector-icons/Ionicons';
    
    import Login from '../views/Login/index';
    import Home from '../views/Home/index';
    import Mine from '../views/Mine/index';
    
    const BottomNavigator = createBottomTabNavigator(
      {
        Home: {
          screen: Home,
          navigationOptions: {
            title: '首页',
            tabBarIcon: ({ focused, horizontal, tintColor }) => {
              return <Ionicons name={'ios-home'} size={25} style={{ color: tintColor }} />;
            },
          },
        },
        Mine: {
          screen: Mine,
          navigationOptions: {
            title: '我的',
            tabBarIcon: ({ focused, horizontal, tintColor }) => {
              return <Ionicons name={'logo-octocat'} size={25} style={{ color: tintColor }} />;
            },
          },
        },
      },
      {
        tabBarOptions: {
          activeTintColor: '#168f48',
        },
      },
    );
    
    const AppNavigator = createStackNavigator(
      {
        Home: {
          screen: BottomNavigator,
          navigationOptions: () => ({
            title: '首页',
            headerBackTitle: null,
          }),
        },
      },
      {
        headerMode: 'none',
      },
    );
    
    const LoginNavigator = createStackNavigator(
      {
        Login: {
          screen: Login,
          navigationOptions: () => ({
            title: '登录',
            headerBackTitle: null,
          }),
        },
      },
      {
        headerMode: 'none',
        // navigationOptions: {
        //   headerStyle: {
        //     backgroundColor: '#f4511e',
        //   },
        //   headerTintColor: '#fff',
        //   headerTitleStyle: {
        //     fontWeight: 'bold',
        //   },
        // },
        // headerLayoutPreset: 'center',
      },
    );
    //路由定义了初始化显示页面
    const App = createSwitchNavigator(
      {
        LoginNavigator,
        AppNavigator,
      },
      {
        initialRouteName: 'LoginNavigator',
      },
    );
    
    //导航注册
    export default createAppContainer(App);
    

    home页面中的数据处理很隐蔽

    componentDidMount() {
        // mockjsInit();
      }
      onPressButton = () => {
        this.setState({
          value: JSON.stringify(5656),
        });
        api
          .list()
          .then((res) => {
            this.setState({
              value: JSON.stringify(777),
            });
          })
          .catch((error) => {
            alert(error.message);
          });
      };
    

    //mine页面很神奇啊,它其实没有定义下面的导航切换啊,为啥它有啊
    //并没有引入navigation但是却可以用
    import React, { Component } from 'react';
    import { StyleSheet, ScrollView, Button, Text, View } from 'react-native';
    
    export default class Home extends Component {
      render() {
        return (
          <View style={styles.container}>
            <Text>MineScreen Screen</Text>
            <Button title="Go to Login" onPress={() => this.props.navigation.navigate('Login')} />
            <Button title="Go to Mine" onPress={() => this.props.navigation.navigate('Mine')} />
            <Button title="Go back" onPress={() => this.props.navigation.goBack()} />
          </View>
        );
      }
    }
    const styles = StyleSheet.create({
      container: {
        flex: 1,
        backgroundColor: '#F5FCFF',
        fontSize: 19,
      },
    });
    

    //其实我觉得mine中的代码有问题

  • 相关阅读:
    最近。。。。。。。。。。。
    SQLServer中 多行合成一行 的方法.
    操作Excel
    minheight和height
    提高网页效率的14条准则
    IE和FireFox的Javascript的事件和事件处理总结
    id和class到底要用哪一个?
    XML.parentNode 与 parentElement 的说明
    window.event 对象详解
    padding和margin到底要用哪一个?
  • 原文地址:https://www.cnblogs.com/smart-girl/p/10879646.html
Copyright © 2011-2022 走看看