0.50版本 react-native

2018-01-19 15:24:51 qq_28978893 阅读数 7373

扫码这个功能在普通项目中用到的案例还是比较多的,签到、加好友、WebView跳转等等

针对扫码这个功能,react-native的前辈们已经封装好了可以跨平台的组件
react-native-camera
亲测是非常好用的,虽然有很多提Issue,但是最新的版本还是比较稳定的

给大家说一下我在用的时候遇到的一个自己挖的坑
因为我的项目有不止一个界面用到了这个功能,所以我在不同的导航器中用到了同一个界面,界面的key值也是相同的,导航倒是没有出现错乱,但是在打开Camera的时候会出现白屏,相机始终不能渲染出来,当然对Key值进行区分,这个问题也就解决了,刚开始以为是组件的问题,去官网一顿找相似的issue

好了,忘记这个issue继续说,UI,功能测试没问题之后发现这个customer界面是真的没做什么优化,真的很丑,所以,拿来微信的扫一扫功能来参考一下

微信爸爸的扫一扫

经过对一些功能的筛选,我们对一些细节进行了模仿

先看一下效果吧

模仿后的效果

说一下具体进行的模仿模块

1、四周阴影和中间全透明的效果实现
实现这个效果我走了点弯路,实现方法也是比较麻烦,先给大家分享一下,我是将界面分成了5部分(View),中间框是一部分,四周是一部份

2、四个绿色的边框角
这四个边框角的原型是两个View,每个View是一条线

<View style={{ position: 'absolute', left: 0, top: 0 }}>
  <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
  <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
</View>

其实就是一横一竖,宽度和高度分别是2,这个是左上角的,右上角的边框是通过左上角的旋转角度而来

<View style={{ position: 'absolute', right: 1, top: -1, transform: [{rotate: '90deg'}] }}>
  <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
  <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
</View>

其他的处理方法类似

3、扫描线
扫描线就是一条线,然后赋予动画,

<Animated.View style={{ width: px2dp(500),
  height: px2dp(2),
  backgroundColor: '#37b44a',
  transform: [{
    translateY: this.state.top.interpolate({
      inputRange: [0, 1],
      outputRange: [0, px2dp(500)]
    })
  }]}} 
/>

而且这个动画是由setInterval定时器进行驱动的

setInterval(function () {
  Animated.timing(that.state.top, {
    toValue: 1,
    duration: 2200
  }).start(() => that.setState({ top: new Animated.Value(0) }))
}, 2260)

接下来我把项目代码脱敏之后给大家共享出来,供参考

class ScannerCodeScreen extends Component {
  static navigationOptions = ({ navigation }) => {
    return ({
      title: '二维码扫描',
      ...ApplicationStyles.blackHeaderStyle,
      headerLeft: <HeaderLeft navigation={navigation} color={Colors.C8} />
    })
  }

  constructor (props) {
    super(props)
    this.state = {
      firstLoad: true,
      top: new Animated.Value(0),
      isSigned: false
    }
    /** object */
    this.resultUrl = null
    /** function */
    this.onBarCodeRead = this.onBarCodeRead.bind(this)
    this.interval = null
  }

  componentDidMount () {
  }

  componentWillReceiveProps (nextProps) {
    if (!this.props.isFocused && nextProps.isFocused) {
      this.onFocus()
    }
    if (this.props.isFocused && !nextProps.isFocused) {
      this.onBlur()
    }
  }

  onFocus () {
    this.props.toggleTabBarAction(false)
    /** 获取视频、现场首页信息 */
    if (this.state.firstLoad) {
      this.setState({ firstLoad: false })
    }
    /** 定时器触发动画 */
    const that = this
    this.interval =
    setInterval(function () {
      Animated.timing(that.state.top, {
        toValue: 1,
        duration: 2200
      }).start(() => that.setState({ top: new Animated.Value(0) }))
    }, 2260)
  }

  onBlur () {
    /** 清除定时任务 */
    clearInterval(this.interval)
  }

  getQueryString (url, name) {
    var reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
    var r = url.substr(1).match(reg)
    if (r != null) {
      return unescape(r[2])
    }
    return null
  }

  onBarCodeRead (e) {
    /** 避免多次提交 */
    console.log(e)
    if (!this.resultUrl || this.resultUrl !== e.data) {
      if (e.data.indexOf('http://www.baidu.com/') !== 0) {
        this.props.toastAction('请扫描正确的二维码')
      } else {
        this.resultUrl = e.data
        const id = this.getQueryString(e.data, 'id')
        this.props.navigation.navigate('applicationMessage', { receiver: id })
        this.resultUrl = null
      }
    }
  }

  barcodeReceived (e) {
    console.log('Barcode: ' + e.data)
    console.log('Type: ' + e.type)
  }

  render () {
    return (
      <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }} >
        <View>
          <Camera
            ref={(cam) => {
              this.camera = cam
            }}
            onBarCodeRead={this.onBarCodeRead.bind(this)}
            style={{ width, height, marginTop: 40 }}
            aspect={Camera.constants.Aspect.fill}
          />
          <View style={{ position: 'absolute', left: 0, right: 0, top: 0, bottom: 0 }}>
            <View style={{ height: (height - px2dp(600)) / 2, backgroundColor: 'black', opacity: 0.5 }} />
            <View style={{ flexDirection: 'row', justifyContent: 'flex-start', alignItems: 'center' }}>
              <View style={{ height: px2dp(500), width: (width - px2dp(500)) / 2, backgroundColor: 'black', opacity: 0.5 }} />
              <View style={{ height: px2dp(500), width: px2dp(500) }} >
                <View style={{ position: 'absolute', left: 0, top: 0 }}>
                  <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
                  <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
                </View>
                <View style={{ position: 'absolute', right: 1, top: -1, transform: [{rotate: '90deg'}] }}>
                  <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
                  <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
                </View>
                <View style={{ position: 'absolute', left: 1, bottom: -1, transform: [{rotateZ: '-90deg'}] }}>
                  <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
                  <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
                </View>
                <View style={{ position: 'absolute', right: 0, bottom: 0, transform: [{rotateZ: '180deg'}] }}>
                  <View style={{ height: 2, width: px2dp(60), backgroundColor: '#37b44a' }} />
                  <View style={{ height: px2dp(60), width: 2, backgroundColor: '#37b44a' }} />
                </View>
                <Animated.View style={{ width: px2dp(500),
                  height: px2dp(2),
                  backgroundColor: '#37b44a',
                  transform: [{
                    translateY: this.state.top.interpolate({
                      inputRange: [0, 1],
                      outputRange: [0, px2dp(500)]
                    })
                  }]}} />
              </View>
              <View style={{ height: px2dp(500), width: (width - px2dp(500)) / 2, backgroundColor: 'black', opacity: 0.5 }} />
            </View>
            <View style={{ flex: 1, backgroundColor: 'black', opacity: 0.5, alignItems: 'center' }} >
              <Text style={{ fontSize: FontSize(28), color: Colors.C5, marginTop: px2dp(40) }}>将二维码放入框内,即可自动扫描</Text>
            </View>
          </View>
        </View>
      </View>
    )
  }
}
2018-03-12 17:01:00 weixin_30449453 阅读数 37

自己测试了下,https://www.jianshu.com/p/eceb7e66fa5e?appinstall=0

记录下自己遇到的问题,以及解决方法,

首先新建一个react native项目,然后 安装 react-native-baidu-map 模块,

安装
  npm install react-native-baidu-map --save
  或者
  yarn add react-native-baidu-map

使用上面2个都是可以的

项目以及 地图组建安装好了,接下来就是配置了:

先打开.xcodeproj 文件进入xcode 配置

 

xcode配置:

  1. 添加 RCTBaiduMap.xcodeproj 

     把  RCTBaiduMap.xcodeproj 文件添加 到下图的 libraries 中,RCTBaiduMap.xcodeproj文件在 你项目工程目录 的 node_modules/react-native-baidu-map/ios 目录下面,

    你也可以找到该目录直接拖到 libraries 中

 

 

2. Build Phases -> Link Binary With Libraries 加入 libRCTBaiduMap.a

  或者

 General -> Linked Frameworks and Libraries   中 加入 libRCTBaiduMap.a

上面2个地方加入是一样的,下图是加好了的

 

3.

在 Build Settings -> Search Paths -> Framework search path  中添加  $(PROJECT_DIR)/../node_modules/react-native-baidu-map/ios/lib

在 Build Settings -> Search Paths -> Header search paths  中添加  $(SRCROOT)/../node_modules/react-native-baidu-map/ios/RCTBaiduMap

 



4.

  Build Phases -> Link Binary With Libraries -> + 号按钮 ->  add other -> node_modules/react-native-baidu-map/ios/lib  目录下的 framwordk 全部选中,然后添加

然后在 Build Phases -> Link Binary With Libraries -> + 号按钮   这里继续添加下面的

CoreLocation.framework
QuartzCore.framework
OpenGLES.framework
SystemConfiguration.framework
CoreGraphics.framework
Security.framework
libsqlite3.0.tbd(xcode7以前为 libsqlite3.0.dylib)
CoreTelephony.framework
libstdc++.6.0.9.tbd(xcode7以前为libstdc++.6.0.9.dylib)

例图:

 

5. 添加  node_modules/react-native-baidu-map/ios/lib/BaiduMapAPI_Map.framework/Resources/mapapi.bundle  下面的  mapapi.bundle 文件,添加位置如下图,可能项目名字不同文件名字不同

 

6.修改 AppDelegate.m  文件

  

#import "RCTBaiduMapViewManager.h" 



{
    ...
    [RCTBaiduMapViewManager initSDK:@"api key"];//这里的api key 一定要在官网和APP的Bundle identifier对应,否则地图会显示失败
    ...
}

 

如图代码添加位置

 

7. build一下,看看是否配置成功

当前我遇到2个问题,记录下

  (1).  报错信息 Redefinition of 'RCTMethodInfo'

  如图

  

解决办法:

find -> find in project         s搜索 RCTBridgeModule.h,  然后找到 引入它的地方 

#import "RCTBridgeModule.h"
换成
#import "React/RCTBridgeModule.h"
或者换成
#import <React/RCTBridgeModule.h>

如图

 

  (2).报错如下图

  

 

解决办法 

#import "RCTViewManager.h"
#import "RCTConvert+CoreLocation.h"

换成

#import <React/RCTViewManager.h>
#import <React/RCTConvert+CoreLocation.h>

 

如图

然后到这一步,配置就没问题,我只遇到这2个问题。

然后在  https://github.com/lovebing/react-native-baidu-map 下载 demo  ,你也可不下载,进去找到 BaiduMapDemo.js,把它的内容拷贝出来,直接放到自己的组建里面,然后引用。

在这里还会有一个问题,就是在你引入这个组建的时候,组建里面在引入  react-native-baidu-map 的时候会报错,

 

报错如图:

 

将 node_modules/react-native-baidu-map/js/MapView.js中的

import React, {
  Component,
  PropTypes
} from 'react';

修改成

import React, {
  Component,
} from 'react';

import PropTypes from 'prop-types';

到这里 就没在遇到问题了,模拟器上以及可以看到地图了,我的 react-native  版本是 0.50.0

 注: 如果本身项目里面没得 prop-types  模块 得下载一个

 

 

转载于:https://www.cnblogs.com/bruce-gou/p/8550290.html

2017-11-05 21:45:45 Aliguagua 阅读数 8097

创建指定的React-Native版本

刚刚开始学习React Native,很多都不懂,搭建环境的时候遇到了挺多问题的,一直在折腾。

我是按照React Native文档来搭建环境的,安装react-native-cli使用的是下面的命令。

npm install -g react-native-cli

安装完之后创建了一个项目test,发现react-native的版本是最新的0.50.1,这个版本目录中是没有index.android.js和index.ios.js这两个文件的,多了index.js和App.js等文件
这里写图片描述

刚学React Native就使用最新的版本肯定会遇到很多别人没有遇到的坑,而且我买的书《React Native跨平台移动应用开发》这本书是使用0.41.0版本的,为了统一所以还是使用低版本吧
结果我想当然的使用react-native init demo @0.41.0 这个命令来创建低版本的项目,结果是不对的,这样创建出来的依然是最新版本的项目。
后来在百度上看到说,在安装react-native-cli的时候可以指定版本,使用npm install -g react-native-cli @0.41.0,然后我把react-native-cli卸载了,重新安装,不管怎么试都是不行的,直接就报错了。也可能是可以的,但是我试了是不行的。
后来又找到了一个方法:

react-native init demo --verbose --version 0.41.0

出自:http://www.jianshu.com/p/717dee645939
我试了是可以的,但是具体原理我是不太懂的。
这里写图片描述
参考:https://stackoverflow.com/questions/34211131/new-react-native-project-with-old-version-of-react-native/37623531#37623531

2019-07-15 15:45:48 daniel1227 阅读数 2201

转载自:https://blog.csdn.net/daniel1227/article/details/95972996

在github上找了很多图表类的插件,大多都是直方图之类的显示完好,到了饼图都差强人意。因为react-native版本更新的快,用不同的版本必须适配不同的第三方库,所以很多repo维护的都比较慢(或者类似于react-native-chart就直接不更新了),如果你非得用某个第三方库,在你当前版本不适合的情况下,要么换库,要么就降级react-native版本。这导致在开发上非常棘手,因为是团队项目,不可能去降级react-native版本的啊,在找适合的第三方库的过程中也是一度陷入了绝望之中。直到在react-native-chart的readme中发现了victory-native。什么鬼。。。。。和我平常在git-hub上搜索的套路完全不一致啊。。。

 

项目地址:https://github.com/FormidableLabs/victory-native

效果:

安装victory-native

首先,先要安装react-native-svg,对应你的react-native版本号进行安装。 

react-native-svg >= 3.2.0 only supports react-native >= 0.29.0
react-native-svg >= 4.2.0 only supports react-native >= 0.32.0
react-native-svg >= 4.3.0 only supports react-native >= 0.33.0
react-native-svg >= 4.4.0 only supports react-native >= 0.38.0 and react >= 15.4.0
react-native-svg >= 4.5.0 only supports react-native >= 0.40.0 and react >= 15.4.0
react-native-svg >= 5.1.8 only supports react-native >= 0.44.0 and react == 16.0.0-alpha.6
react-native-svg >= 5.2.0 only supports react-native >= 0.45.0 and react == 16.0.0-alpha.12
react-native-svg >= 5.3.0 only supports react-native >= 0.46.0 and react == 16.0.0-alpha.12
react-native-svg >= 5.4.1 only supports react-native >= 0.47.0 and react == 16.0.0-alpha.12
react-native-svg >= 5.5.1 only supports react-native >= 0.50.0 and react == 16.0.0

 

之后link一下

react-native link react-native-svg

重新打包安装

react-native run-ios
// or
react-native run-android

然后安装victory-native

yarn add victory-native

 

使用

先引入,这里只讨论折线图,不过很多参数都是共同的,其他的见官方文档

import { VictoryLine, VictoryChart, VictoryTheme } from 'victory-native';

使用组件(moment组件是一个专门用来计算日期的js组件)

<VictoryChart theme={VictoryTheme.material} minDomain={{ y: 0 }}>
                <VictoryLine
                  style={{ data: { stroke: '#c43a31' } }}
                  data={[
                    {
                      x: moment()
                        .subtract(6, 'days')
                        .format('MM-DD'),
                      y: this.state.sevenDayConutData ? this.state.sevenDayConutData[0] : 0
                    },
                    {
                      x: moment()
                        .subtract(5, 'days')
                        .format('MM-DD'),
                      y: this.state.sevenDayConutData ? this.state.sevenDayConutData[1] : 0
                    },
                    {
                      x: moment()
                        .subtract(4, 'days')
                        .format('MM-DD'),
                      y: this.state.sevenDayConutData ? this.state.sevenDayConutData[2] : 0
                    },
                    {
                      x: moment()
                        .subtract(3, 'days')
                        .format('MM-DD'),
                      y: this.state.sevenDayConutData ? this.state.sevenDayConutData[3] : 0
                    },
                    {
                      x: moment()
                        .subtract(2, 'days')
                        .format('MM-DD'),
                      y: this.state.sevenDayConutData ? this.state.sevenDayConutData[4] : 0
                    },
                    {
                      x: moment()
                        .subtract(1, 'days')
                        .format('MM-DD'),
                      y: this.state.sevenDayConutData ? this.state.sevenDayConutData[5] : 0
                    },
                    {
                      x: moment().format('MM-DD'),
                      y: this.state.sevenDayConutData && this.state.sevenDayConutData ? this.state.sevenDayConutData[6] : 0
                    }
                  ]}
                  labels={datum => (datum.y > 0 ? datum.y : '')}
                  scale="time"
                />
              </VictoryChart>

参数

看下官方文档,写的非常详尽。

参考资料

  1. react-native-svg repo 地址
  2. victory-native repo 地址
  3. victory官方文档
  4. moment官网
2017-08-23 16:43:00 gang544043963 阅读数 38363

前言

从2017年初开始到现在,使用React-Native做项目已经一年了。我们做的是一款IM软件,嵌入在一个手机游戏平台的工程内部。之所以要采用react-native(后文简称RN)框架重构它,是因为现在游戏大厅上的所有游戏都是热更新的,为了也能让这个IM软件实现实时更新,减少IPA升级的次数,RN当然是不错的选择。

经过一个同事将近一年的预研以后,2017年我们全面开启项目重构。奔着热更新和Write once, run everywhere,从此走上RN填坑之旅。

从ES6,css-layout,redux开始

我一直在从事iOS开发,用OC语言,接触到ES6还是挺新鲜的。语言风格和C系语言完全不是一个风格。参考阮一峰老师的教程http://es6.ruanyifeng.com/#docs/intro
RN采用标签式的界面布局,叫css-layout,和CSS基本一样。虽然是第一次使用这种方式布局界面,用熟之后觉得还是很方便的,代码量少,很直接。
聊天部分我们使用了redux架构,是JavaScript的一个状态机。参考http://www.redux.org.cn/index.html

RN的优势

  • 调试方便
    ipa安装好之后,就不需要频繁编译了,只需要reload一下,把js代码从云服务器下载下来就可以呈现改变代码后的效果。而且RN支持hotReload,在调试界面的时候非常方便,修改代码之后保存,界面就自动跟着变化,这一点在调试的时候实在很爽,不过有时候有点慢,需要reload。chrome在线调试也挺不错,可以打断点,看日志。虽然没有xcode或者Android Studio那么浑然一体,但是作为脚本语言的调试工具,也是很厉害了。

  • css-layout布局
    这对于前端程序员来说,降低了不少学习成本,也大大减少了代码量。但是对于iOS或者安卓开发者来说,刚开始接触的时候,得接受一些思想上的转变。

  • 跨平台
    大多数代码,只需要写一套,安卓和iOS就都可以运行了,游戏逻辑和数据。界面上一部分有一些平台区分,毕竟是从react包装上来的。刚开始学iOS的时候,就想象着,要是有一种跨平台的开发形式就很6了,没想到过了几年就有了。跨平台理论上是可以减少开发成本的,减少开发人员数量,但是实际效果并不然,后面说。

  • 热更新
    这可能也是大多数公司选择使用RN的主要原因。频繁的app升级会让用户很烦,而且苹果的审核真是很麻烦。现在很多大型app都使用了RN,毕竟繁多的业务迭代,每次都通过APP审核,也算是噩梦啊。

  • 有个好爹
    有着Facebook的支撑,相信会发展的很好。

RN的不完善

容我吐槽一下,不完善的地方实在太多了,和原生开发体验来比,堪称天壤之别。RN现在的最新版本是0.46,我们工程中用的是0.42,毕竟还没上1.0呢。
去掉主观情感,下面列举一下部分不完善的点:

  • 开发体验一般。
    虽然js语法很灵活,但毕竟是脚本语言,调试起来还是不方便,不好查错。我们用的表现较好的vscode编辑器,就这都感觉各种跳转很不方便,动不动就得全局搜索,可能是xcode用习惯了吧。脚本语言的编写也会慢慢习惯吧。

  • 文档很粗略
    官网上的文档,就只是简单介绍用法和各个控件的属性,对细节的描述很少。当你遇到难解决的问题或者踩到坑了,上面基本找不到答案。

  • 两个平台还没有完全统一
    很多控件都是iOS专属,或者安卓专属。还有同一些控件,在不同平台上表现差异很大。

  • 控件不完善
    这个其实挺多的,最基本的ListView,功能缺失,坑很多。Text不支持富文本,动画,手势,ScrollView等等等等。不能一一列举。作为聊天软件,富文本功能必须实现啊,用于emoji表情和文字的混合显示。被迫自己搞了一套实现方案,现在还有点小bug。具体实现方案参考http://blog.csdn.net/gang544043963/article/details/70245850

  • 升级RN版本需要大动干戈
    近期我们做了一次RN版本升级,从原来的0.42升到最近的0.50。真的挺麻烦。新版把PropTyps从React中移了出来,那么之前的引用方式就得变,所有的文件挨个查。之前使用的第三方库,有和PropTyps相关的,都得一一更新。之前很多界面布局的时候,在image上放置了一些其他控件,升级后会报错,然后一一调整。

  • 要做出优质app需要花费大量人力和时间去打磨
    跨平台,其实并没有减少开发成本,原来我们安卓和iOS各三个人,每次迭代都是有序进行。然而换了RN之后,6个人全上,做的累的啊,迭代慢,bug多。

总结

FaceBook也是想为开发者带去一套跨平台、动态更新的 Javascript 框架,口号是:Learn once, write anywhere:Build mobile apps with React。我觉得这是一个伟大的梦想。

2015年刚发布的时候,充满了期待和争议。发展到现在,RN也是逐渐在完善。前一段时间苹果发警告邮件的事情引起了大家的恐慌,不过以我看,RN还是安全的。从苹果的审核政策来看,允许运行于JavascriptCore的动态加载代码,并且没有去使用人家的私有方法。而且,现在使用RN的大公司挺多,尽管苹果高傲,但是要禁止RN的话,还是得掂量一下这些大企业的意见吧。

RN目前确实还不够成熟稳定,所以,想入坑的开发人员和决策者在入坑前得多权衡。虽然作为技术开发者应该具备对新技术的敏锐嗅觉和快速学习能力,但是对于项目的技术更新,还得要根据实际情况,要慎重。用户体验,开发成本,是两个最重要的权衡指标。

毕竟,不管是react-native,JSPatch,还是其他人更新技术,从户用体验和开发体验来说,都是开倒车的。

RN适合什么人或公司

  • 迫切需要热更新功能
  • 愿意投入人力和财力给RN

其他普通的应用,没那么迫切需要热更新的,就好好使用原生开发,毕竟原生的成熟度和稳定性要比RN好很多。