原生视图都需要被一个RCTViewManager的子类来创建和管理。这些管理器在功能上有些类似“视图控制器”,但它们本质上都是单例 - React Native只会为每个管理器创建一个实例。它们创建原生的视图并提供给RCTUIManager,RCTUIManager则会反过来委托它们在需要的时候去设置和更新视图的属性。RCTViewManager还会代理视图的所有委托,并给JavaScript发回对应的事件。
提供原生视图很简单:
首先创建一个子类
添加RCT_EXPORT_MODULE()标记宏
实现-(UIView *)view方法
#import "RNTMapManager.h"
#import "RCTConvert+Mapkit.h"
@interface RNTMapManager ()
@end
@implementation RNTMapManager
RCT_EXPORT_MODULE();
-(UIView *)view{
MKMapView *view = [[MKMapView alloc]init];
view.pitchEnabled=NO;
view.showsTraffic = YES;
view.showsUserLocation = YES;
view.delegate = self;
return view;
}
MapView.js代码如下:
import React, { Component,PropTypes } from 'react';
import {
requireNativeComponent
} from 'react-native';
var RNTMap = requireNativeComponent('RNTMap', MapView);
export default class MapView extends Component {
render() {
return ;
}
}
在index.ios.js中引入MapView.js代码如下:
import MapView from './MapView';
class App extends Component{
return(
);
}
}
const styles = StyleSheet.create({
container:{
flex:1,
marginTop:20,
backgroundColor:'red',
},
}
这时候已经可以看到地图出现了
2.原生像js提供属性,供js操作控制
通过RCT_EXPORT_VIEW_PROPERTY()宏可以向js提供属性
比如
在上面RNTMapManager.m里添加
RCT_EXPORT_VIEW_PROPERTY(showsScale, BOOL)//注意这里的属性名字要和原生的属性名字要一致
然后在index.ios.js的render方法里
render(){
return(
);
}
这时候就可以看到左上角出现的比例
3.添加自定义属性
这里稍微复杂一点 实现当我们在JS里改变地图的可视区域的时候,视角会平滑地移动过去
首先通过RCT_CUSTOM_VIEW_PROPERTY添加自定义属性
在RCTMapView.m里面添加自定义属性region
RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RNTMap){
[view setRegion:json? [RCTConvert MKCoordinateRegion:json] :defaultView.region animated:YES];
};
然后创建一个RNTMap继承MKMapView
RNTMap.h代码如下(RNTMap.m暂时不需要实现其他代码)
#import
#import
@interface RNTMap : MKMapView
@property(nonatomic,copy)RCTBubblingEventBlock onChange;
@end
RCTMapManager.m里面的-(UIView *)view替换成下面的
-(UIView *)view{
MKMapView *view = [[MKMapView alloc]init];
view.pitchEnabled=NO;
view.showsTraffic = YES;
view.showsUserLocation = YES;
view.delegate = self;
return view;
}
下面开始写MapView.js代码如下
var RNTMap = requireNativeComponent('RNTMap', MapView);
export default class MapView extends Component {
render() {
return ;
}
}
//这里解决用户要想知道我们的组件有哪些的问题,我们可以创建一个封装组件,并且通过PropTypes来说明这个组件的接口
MapView.PropTypes={
pitchEnabled:React.PropTypes.bool,
region:React.PropTypes.shape({
latitude: React.PropTypes.number.isRequired,
longitude: React.PropTypes.number.isRequired,
latitudeDelta: React.PropTypes.number.isRequired,
longitudeDelta: React.PropTypes.number.isRequired,
}),
}
index.ios.js render代码如下
render(){
var region = {
latitude:30.40,
longitude:120.51,
latitudeDelta:0.1,
longitudeDelta:0.1,
};
return(
);
}
效果如下图(本页的图片都是模拟器 经纬度显示可能不准确):