React Native填坑之旅 -- 使用iOS原生视图(高德地图)

在开发React Native的App的时候,你会遇到很多情况是原生的视图组件已经开发好了的。有的是系统的SDK提供的,有的是第三方试图组件,总之你的APP可以直接使用的原生视图是很多的。React Native提供了一套完善的机制,你可以非常简单的用来包装已有的原生视图。

http://www.cnblogs.com/sunshine-anycall/p/6472029.html

代码地址:https://github.com/future-challenger/react-native-gaode-map

下面就用高德地图作为例子讲解如何包装原生视图。高德地图本身不仅有视图需要展示,还有一些和React Native交互的部分。比如给Js代码发送事件,接受Js发送的方法调用等。

简单实现

基本山只需要三步就可以达到目的:

创建RCTViewManager的子类

在源文件里添加RCT_EXPORT_MODULE()宏的调用

实现- (UIView *)view方法

看看代码:

//.h#import#import@interfaceGDMapViewManager:RCTViewManager@end//.m#import"GDMapViewManager.h"#import"GDMapView.h"#import#import@implementationGDMapViewManagerRCT_EXPORT_MODULE()- (UIView*)view {  MAMapView *mapView = [[MAMapView alloc] init];  mapView.showsUserLocation =YES;// 显示用户位置蓝点mapView.userTrackingMode = MAUserTrackingModeFollow;returnmapView;}@end// index.ios.js// import from `react` & `react native`...import { requireNativeComponent } from'react-native'constGDMapView = requireNativeComponent('GDMapView', null)

exportdefaultclass mobike extends Component {

render() {return(

);

}

}// styles...

属性

要导出属性:

RCT_EXPORT_VIEW_PROPERTY(showsCompass,BOOL)

这里导出的属性是高德地图的内置属性,表示是否在地图上显示指南针。可以如此使用:

如果是我们自定义的属性,而不是高德地图内置的属性该如何导出呢?来看一个例子:

RCT_CUSTOM_VIEW_PROPERTY(center,CLLocationCoordinate2D,GDMapView){[viewsetCenterCoordinate:json?[RCTConvert CLLocationCoordinate2D:json]:defaultView.centerCoordinate];}

写这个属性是因为出过来的参数是json串,只有最初是的类型NSString、int之类的可用,其他类型的都需要转化。比如这里要用的CLLocationCoordinate2D这个类型。所以我们需要判断js传过来的json是否为空,并在不为空的时候转化成CLLocationCoordinate2D对象。如果js传过来的json为空的话则使用defaultView.centerCoordinate来填充。

处理用户发出的事件

处理直接或者间接的从用户发出的事件。比如,用户对地图的各种操作都会生成对应的事件需要原生代码来处理。

要实现这部分功能基本只需要两步:

在视图部分添加一个属性:@property (nonatomic, copy) RCTBubblingEventBlock onChange;

在视图Manager部分暴露出这个属性:RCT_EXPORT_VIEW_PROPERTY(onChange, RCTBubblingEventBlock)

之后在相对应的地方调用就可以了,如:

-(void)mapView:(GDMapView*)mapView regionDidChangeAnimated:(BOOL)animated{if(!mapView.onChange){return;}MACoordinateRegion region=mapView.region;mapView.onChange(@{@"region":@{@"latitude":@(region.center.latitude),@"longitude":@(region.center.longitude),@"latitudeDelta":@(region.span.latitudeDelta),@"longitudeDelta":@(region.span.longitudeDelta),}});}

建立对应的Js组件

上文的方式使用原生组件会显得凌乱,不易控制。最好的方式就是建立一个对应的Js组件。

importReactfrom'react';import{requireNativeComponent}from'react-native';exportdefaultclassMapViewextendsReact.Component{constructor(props){super(props)}render(){return()}}MapView.propTypes = {marker: React.PropTypes.object,markers: React.PropTypes.array,zoom: React.PropTypes.number,centerCoordinate: React.PropTypes.object,showScale: React.PropTypes.bool,showsCompass: React.PropTypes.bool,};varGDMapView = requireNativeComponent('GDMapView', MapView);

之后就可以这样使用了:

注意,给Js组件定义PropTypes是必须的。而且我这里的定义还是有点模糊。官网的比较细致,列在这里:

MapView.propTypes={region:React.PropTypes.shape({/*** Coordinates for the center of the map.*/latitude:React.PropTypes.number.isRequired,longitude:React.PropTypes.number.isRequired,/*** Distance between the minimum and the maximum latitude/longitude* to be displayed.*/latitudeDelta:React.PropTypes.number.isRequired,longitudeDelta:React.PropTypes.number.isRequired,}),};

官网的例子对region这prop定义的相当的细致,不是一个`React.PropTypes.object就过去了的。

还有一些属性,你不想它们作为对应Js组件的API的一部分。所以,需要隐藏起来。那么你可以在绑定原生组件和Js组件的时候指定它们不作为API的一部分。如:

constGDMapView=requireNativeComponent('GDMapView',MapView,{nativeOnly:{onChange:true}});

在对应的组件里处理事件

在本组件内绑定原生组件的onChange事件,如这里的_onChange()方法。

在绑定好的方法里(如_onChange()方法内)调用外部传入的事件处理方法(如this.props.onRegionChange)

当然,你不会忘了给this.props.onRegionChange写PropTypes的。

exportdefaultclassMapViewextendsReact.Component{constructor(props){super(props)this._onChange=this._onChange.bind(this);}_onChange(event){if(!this.props.onRegionChange){return;}this.props.onRegionChange(event.NativeEvent.region)}render(){return()}}MapView.propTypes = {//...onRegionChange: React.PropTypes.func,};constGDMapView = requireNativeComponent('GDMapView', MapView, {nativeOnly: { onChange:true}});

填坑完毕

到这里你可以在React Natie里愉快的使用原生组件了。

后面我们来探讨一下在Android里如何处理这些问题。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容