原生視圖都需要被一個RCTViewManager的子類來創(chuàng)建和管理蚓庭。這些管理器在功能上有些類似“視圖控制器”任连,但它們本質(zhì)上都是單例 - React Native只會為每個管理器創(chuàng)建一個實例。它們創(chuàng)建原生的視圖并提供給RCTUIManager耳舅,RCTUIManager則會反過來委托它們在需要的時候去設(shè)置和更新視圖的屬性隘世。RCTViewManager還會代理視圖的所有委托栈雳,并給JavaScript發(fā)回對應的事件忘苛。
提供原生視圖很簡單:
首先創(chuàng)建一個子類
添加RCT_EXPORT_MODULE()標記宏
實現(xiàn)-(UIView *)view方法
#import "RNTMapManager.h"
#import "RCTConvert+Mapkit.h"
@interface RNTMapManager ()<MKMapViewDelegate>
@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 <RNTMap {...this.props} />;
}
}
在index.ios.js中引入MapView.js代碼如下:
import MapView from './MapView';
class App extends Component{
return(
<MapView style={styles.container}
showsScale={true}
/>
);
}
}
const styles = StyleSheet.create({
container:{
flex:1,
marginTop:20,
backgroundColor:'red',
},
}
這時候已經(jīng)可以看到地圖出現(xiàn)了
2.原生像js提供屬性蝉娜,供js操作控制
通過RCT_EXPORT_VIEW_PROPERTY()宏可以向js提供屬性
比如
在上面RNTMapManager.m里添加
RCT_EXPORT_VIEW_PROPERTY(showsScale, BOOL)//注意這里的屬性名字要和原生的屬性名字要一致
然后在index.ios.js的render方法里
render(){
return(
<MapView style={styles.container}
showsScale={true}
/>
);
}
這時候就可以看到左上角出現(xiàn)的比例
3.添加自定義屬性
這里稍微復雜一點 實現(xiàn)當我們在JS里改變地圖的可視區(qū)域的時候,視角會平滑地移動過去
首先通過RCT_CUSTOM_VIEW_PROPERTY添加自定義屬性
在RCTMapView.m里面添加自定義屬性region
RCT_CUSTOM_VIEW_PROPERTY(region, MKCoordinateRegion, RNTMap){
[view setRegion:json? [RCTConvert MKCoordinateRegion:json] :defaultView.region animated:YES];
};
然后創(chuàng)建一個RNTMap繼承MKMapView
RNTMap.h代碼如下(RNTMap.m暫時不需要實現(xiàn)其他代碼)
#import <MapKit/MapKit.h>
#import <React/RCTComponent.h>
@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 <RNTMap {...this.props} />;
}
}
//這里解決用戶要想知道我們的組件有哪些的問題扎唾,我們可以創(chuàng)建一個封裝組件召川,并且通過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(
<MapView style={styles.container}
showsScale={true}
region={region}
/>
);
}
效果如下圖(本頁的圖片都是模擬器 經(jīng)緯度顯示可能不準確):