React-Native自定义view显示(原生端)

来源:互联网 发布:淘宝写论文有靠谱的吗 编辑:程序博客网 时间:2024/04/25 23:00

参考:http://blog.csdn.net/pz789as/article/details/52448048


自定义view: 自己写原生的view显示在RN界面上。


这次主要是项目需要绘制一张大图,里面有很多节点和线,如果使用单纯RN提供的view去做,需要的内存不够(量级在K以上),所以需要想办法在一个view中画所有的点和线。


自己在想的过程中,也去找了一些相关的RN插件,一个是react-native-svg,很好的插件,由于我需要动态更改节点和线的位置,这个插件不能很好的展示,所以放弃了。另外找到一个办法,这个其实就是svg提示,因为svg就是封装了RN自带的ART组件,该组件是RN提供,可以绘制各种图形,虽然可以变换位置等,也有很大弊端,不能使用setNativeProps函数,这个比较要命。因为频繁更新,不用这个函数很容易卡死。


最后辗转了各个网页,实在没办法打算自己写一个。


还好RN留下的借口很牛逼,可以嵌入各种自己写的原生代码。跟着教程写的,具体操作可以看下面网址:

点击打开链接


这里简单说下重点,因为当时自己看的时候也是没看懂(主要是这个api直接拿RNMap去举例,并没有其他的)

1,在xcode里面创建2个类,分别RCT***.h .m 和 RCT***Manager.h .m,这貌似是RN规定的固定写法(自己也不知道,反正照着葫芦画瓢就好了)?

 

我这里多写了一个,自己懵懂,是按照一个插件去写的,其实实现drawRect可以写在RCTDrawView里面,我多写了一步;


2,Manager类需要继承 RCTViewManager

//  RCTDrawViewManager.h#import "RCTViewManager.h"@interface RCTDrawViewManager : RCTViewManager@end
另一个就继承UIView就可以了。关键点是Manager这个,它相当于是原生和RN的桥梁,如果做过RN的原生模块就知道,和模块类似。

@implementation RCTDrawViewManagerRCT_EXPORT_MODULE();@synthesize bridge = _bridge;- (UIView *)view{  return [[RCTDrawView alloc] init];}RCT_EXPORT_VIEW_PROPERTY(backgroundColor, UIColor);RCT_EXPORT_VIEW_PROPERTY(drawData, NSDictionary);RCT_EXPORT_VIEW_PROPERTY(transPos, CGPoint);RCT_EXPORT_VIEW_PROPERTY(scaleValue, CGPoint);//RCT_CUSTOM_VIEW_PROPERTY(transPos, TransPos, RCTDrawView)//{//  [view setTransPos:json ? [RCTConvert TransPos:json] : defaultView.transPos];//}- (dispatch_queue_t)methodQueue{  return dispatch_get_main_queue();}@end

RCT_EXPORT_MODULE 导出模块,可以加个参数,字符串,标识这个模块的名称

RCT_EXPORT_VIEW_PROPERTY 导出属性,可以在js那边设置,如: <DrawView transPos={{x:0,y:0}}/>,我这里是要传一个偏移位置,所以通过JSON的格式传递,很多复杂的数据都可以这样传递,我的drawData就是,传到这边之后可以通过RCTConvert去转换成NSDictionary,当然RN也给我们封装了些常用的,如CGPoint,CGRect等等,可以去RCTConvert中查看,很丰富。

methodQueue 这个是指定线程,因为RN规定渲染需要在主线程中,所以添加这一句话,标识运行在哪个线程中,有很多第三方SDK可能需要这个设定,比如语音识别。


3,RCTDrawVIew里面主要说一点,就是在Manager里面定义的属性,需要在这个里面实现,或者说接收,比如我自己定义的

- (void)setBackgroundColor:(UIColor *)backgroundColor{  if ([_backgroundColor isEqual:backgroundColor]) {    return;  }    _backgroundColor = backgroundColor;  [self layoutSubviews];}-(void)setTransPos:(CGPoint)transPos{  self.drawView.transPos = transPos;  [self layoutSubviews];}-(void)setScaleValue:(CGPoint)scaleValue{  self.drawView.scaleValue = scaleValue;  [self layoutSubviews];}-(void)setDrawData:(NSDictionary *)drawData{  self.drawView.drawData = drawData;  [self layoutSubviews];}

名称都是一一对应的,前面加一个set就可以了。每次在js端设置了属性变更,就会触发这里的set函数,然后就可以做你想做的任何事情了。

我是要更新drawRect,所以要手动的设置 [self.drawViewsetNeedsDisplay]; ,这样一来,就可以更新drawRect里面的内容啦


4,下面看看解析drawData,主要是RCTConvert去转换。

NSArray * orderKey = [RCTConvert NSArray:_drawData[@"order"]];  for (NSString *key in orderKey) {    NSArray* array = [RCTConvert NSArray:_drawData[key]];    if ([key containsString:@"lines"]){      for (int i=0; i<array.count; i++) {        color = [RCTConvert UIColor:array[i][@"color"]];        CGContextSetStrokeColorWithColor(context, color.CGColor);        CGContextSetLineWidth(context, [RCTConvert CGFloat:array[i][@"stroke"]]);        CGPoint aPoints[2];//坐标点        aPoints[0] =CGPointMake([RCTConvert CGFloat:array[i][@"x1"]], [RCTConvert CGFloat:array[i][@"y1"]]);//坐标1        aPoints[1] =CGPointMake([RCTConvert CGFloat:array[i][@"x2"]], [RCTConvert CGFloat:array[i][@"y2"]]);//坐标2        CGContextAddLines(context, aPoints, 2);//添加线        CGContextDrawPath(context, kCGPathStroke); //根据坐标绘制路径      }    }
  }
<span style="font-family: Arial, Helvetica, sans-serif;">}</span>


代码:

源码查看



0 0
原创粉丝点击