React Native原生UI封装以及事件处理

对于目前的移动端原生开发来说,想要完成一个app的开发工作是比较容易的,因为原生代码在网上所提供出来的各种开源的第三方组件已经成千上万了,足以支撑起你的业务需求。但是如果我们想要在React Native上使用第三方组件怎么办?
众所周知,React Native自身框架也提供了一部分基础组件,已经可以基本满足我们的开发需求,但是,当我们需要使用第三方接口的时候该如何?目前市面上基本所有的第三方组件接口都还不提供对React Native的支持,所以,需要使用第三方的时候,还得我们自己来封装处理。
接下来,我们一步一步来封装友盟分享的组件。

1、首先导入友盟分享SDK,然后添加相关的底层依赖文件:
0_1473132391960_屏幕快照 2016-09-06 上午9.05.37.png

底层依赖库的添加:项目 --> build phases --> link binary with libraries在link binary with libraries中点加号,添加上图中的依赖文件,如下图所示。

2、 添加好依赖文件之后,我们接下来完成在原生中的那部分代码。(1) 在AppDelegate中的application:didFinishLaunchingWithOptions: 方法中设置友盟AppKey:

// 设置友盟AppKey[UMSocialData setAppKey:@"57355f3e67e58ed0a50030a1"];

(2) 写一个分享按钮类,继承于UIButton,然后在其中引入友盟分享头文件UMSocial.h,接下来就可以写按钮触发的分享事件了。

#import "MyShareBt.h"
#import "UMSocial.h"

@implementation MyShareBt
//分享按钮初始化
- (instancetype) initWithFrame:(CGRect)frame{
  if ((self = [super initWithFrame:frame])) {
    [self addTarget:self action:@selector(share)
   forControlEvents:UIControlEventTouchUpInside];
  }
  return self;
}

// 按钮分享事件
- (void)share {
  [UMSocialSnsService presentSnsIconSheetView:[UIApplication sharedApplication].keyWindow.rootViewController appKey:@”yourAppKey” shareText:@”test” shareImage:[UIImage imageNamed:@”yourImageName”] shareToSnsNames:[NSArray arrayWithObjects:UMShareToWechatSession,UMShareToWechatTimeline,UMShareToQzone,UMShareToSina,UMShareToTencent,nil]  delegate:nil];
}

@end

(3)穿件分享组件Manager类,该类继承于RCTViewManager。创建好之后,添加标记宏RCT_EXPORT_MODULE()将改模块导出作为一个组件。最后实现-(UIView *)view方法。代码如下:

#import "shareButtonManager.h"
#import "RCTViewManager.h"
#import "UMSocial.h"
#import "MyShareBt.h"

@interface shareBt : RCTViewManager

@property (nonatomic) MyShareBt *bt;

@end

@implementation shareBt

RCT_EXPORT_MODULE()

- (UIView *)view
{
  _bt = [[MyShareBt alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
  return _bt;
}

@end

至此,原生部分代码最基本的展示部分完成了,接下来就需要在JS中进行进一步封装,以提供给JS调用。

3、接下来实现JS中的组件封装与简单调用。

首先导入原生组件,从导入中取得我们所创建的组件,将其作为默认的组件导出,以供其他JS调用。这里,我们其实可以直接在其他JS中调用了,但是为了进行参数的封装,我们也需要将其封装成一个单独的组件。

import React, { Component, PropTypes } from 'react';
import { requireNativeComponent} from 'react-native';

var ShareBt = requireNativeComponent('shareBt', ZKShareBt);

export default class ZKShareBt extends Component {
  render() {
    return (
      <ShareBt {...this.props} />
    );
  }
}

封装组件的调用。下图所示是前面封装组件的调用,这里我们已经封装了很多JS需要传递给原生的参数,接下来,我们就来说说参数以及事件处理的封装。

<ZKShareBt style={styles.map}
            appKey={'57355f3e67e58ed0a50030a1'}
            shareText={'这是分享内容'}
            imageName={'logo'}
            //myTitle = {this.state.btText}//设置分享按钮标题
            //color={this.state.color}//设置分享按钮标题字体颜色
            btImageName = {'share_icon'} //设置分享按钮图片
   />
4、参数的封装

(1) 定义需要传递的参数

#import <UIKit/UIKit.h>

@interface MyShareBt : UIButton

@property (nonatomic, copy) NSString * appKey;//友盟appkey
@property (nonatomic, copy) NSString * shareText;//分享的文本
@property (nonatomic, copy) NSString * imageName;//分享的图片
@property (nonatomic, copy) NSString * myTitle;//分享按钮标题
@property (nonatomic) UIColor * color;//按钮标题字体颜色
@property (nonatomic, copy) NSString * btImageName;//分享按钮图片

@end

(2)以上参数是我们需要从JS传递给原生的,所以我们首先在原生代码中定义好所需要的参数。定义好之后,我们需要使用RCT_EXPORT_VIEW_PROPERTY宏将其导出给JS。

#import "shareButtonManager.h"
#import "RCTViewManager.h"
#import "UMSocial.h"
#import "MyShareBt.h"

@interface shareBt : RCTViewManager

@property (nonatomic) MyShareBt *bt;

@end

@implementation shareBt

RCT_EXPORT_MODULE()

- (UIView *)view
{
  _bt = [[MyShareBt alloc] initWithFrame:CGRectMake(0, 0, 0, 0)];
  return _bt;
}
//将所需参数导出给JS
RCT_EXPORT_VIEW_PROPERTY(appKey, NSString)
RCT_EXPORT_VIEW_PROPERTY(shareText, NSString)
RCT_EXPORT_VIEW_PROPERTY(imageName, NSString)
RCT_EXPORT_VIEW_PROPERTY(myTitle, NSString)
RCT_EXPORT_VIEW_PROPERTY(color, UIColor)
RCT_EXPORT_VIEW_PROPERTY(btImageName, NSString)

@end

(3)重写参数set方法,并给按钮属性赋值,设置UI。

#import "MyShareBt.h"
#import "UMSocial.h"

@implementation MyShareBt

- (instancetype) initWithFrame:(CGRect)frame{
  if ((self = [super initWithFrame:frame])) {
    [self addTarget:self action:@selector(share)
   forControlEvents:UIControlEventTouchUpInside];
  }
  return self;
}
//重写所传递参数的set方法,并将传递过来的参数用于设置UI
- (void)setMyTitle:(NSString *)myTitle{
  [self setTitle:myTitle forState:UIControlStateNormal];
}

- (void)setColor:(UIColor *)color{
  [self setTitleColor:color forState:UIControlStateNormal];
}

- (void)setBtImageName:(NSString *)btImageName{
  [self setBackgroundImage:[UIImage imageNamed:btImageName] forState:UIControlStateNormal];
}

- (void)share {
  [UMSocialSnsService presentSnsIconSheetView:[UIApplication sharedApplication].keyWindow.rootViewController appKey:_appKey shareText:_shareText shareImage:[UIImage imageNamed:_imageName] shareToSnsNames:[NSArray arrayWithObjects:UMShareToWechatSession,UMShareToWechatTimeline,UMShareToQzone,UMShareToSina,UMShareToTencent,nil]  delegate:nil];
}

@end

(4)在JS中将参数封装起来。

import React, { Component, PropTypes } from 'react';
import { requireNativeComponent} from 'react-native';

var ShareBt = requireNativeComponent('shareBt', ZKShareBt);

export default class ZKShareBt extends Component {
  static propTypes = {
    /**
    *
    * 定义组件需要传到原生端的属性
    * 使用React.PropTypes来进行校验
    */
    //使用第三方分享时设置的appKey
    appKey:PropTypes.string,

    //要分享的内容
    shareText:PropTypes.string,

    //需要分享的图片名字(需要事先放在xcode工程中,只需要名字,不需要路径)
    imageName:PropTypes.string,

    //分享按钮标题
    myTitle:PropTypes.string,

    //分享按钮标题颜色
    color:PropTypes.string,

    //分享按钮图片
    btImageName:PropTypes.string,
  };
  render() {
    return (
      <ShareBt {...this.props} />
    );
  }
}

封装好之后,就可以直接调用了。

<ZKShareBt style={styles.map}
            appKey={'57355f3e67e58ed0a50030a1'}
            shareText={'分享内容'}
            imageName={'logo'}
            //myTitle = {this.state.btText}//设置分享按钮标题
            //color={this.state.color}//设置分享按钮标题字体颜色
            btImageName = {'share_icon'} //设置分享按钮图片
   />

运行结果:


0_1473329073169_Simulator Screen Shot 2016年9月6日 上午10.22.29.png
(第一张图中,一不小心封装了其他App中的视图,这里可以通过fetch请求网络数据,获取流量之后传给原生并根据值的变化动态显示流量所占百分比。请自动忽略。。。。。。)
以上是涉及到UI以及相关参数传递的封装工作,接下来,需要做的是事件的封装。这里事件封装用到的是RCTBubblingEventBlock宏。封装事件是,首先,我们需要首先在原生中先定义好需要在JS调用的方法模块。和之前参数定义一样,放在原生UI模块.h文件中

MyShareBt.h
/** button点击事件*/
@property (nonatomic, copy) RCTBubblingEventBlock onButtonClicked;

和参数一样,接下来需要导出:

shareButtonManager.m
RCT_EXPORT_VIEW_PROPERTY(onButtonClicked, RCTBubblingEventBlock)

导出之后,这里我就简单的定义一个分享按钮点击时触发的Delegate方法

MyShareBt.h
@protocol ShareButtonClickedDelegate <NSObject>
@optional
//代理方法
- (void)ButtonClicked;
@end
@property (nonatomic, strong) id <ShareButtonClickedDelegate> ClickDelagate;

该代理方法在按钮点击分享的时候执行:

MyShareBt.m
- (void)share {
  //调用代理方法
  [self.ClickDelagate ButtonClicked];
  //友盟分享
  [UMSocialSnsService presentSnsIconSheetView:[UIApplication sharedApplication].keyWindow.rootViewController appKey:_appKey shareText:_shareText shareImage:[UIImage imageNamed:_imageName] shareToSnsNames:[NSArray arrayWithObjects:UMShareToWechatSession,UMShareToWechatTimeline,UMShareToQzone,UMShareToSina,UMShareToTencent,nil]  delegate:nil];
}

接下来,是实现该代理方法(我在这里设了一个随机数,传到JS中,提供给JS使用,后面JS就可以直接使用传过去的这个随机数):

shareButtonManager.m
#pragma mark ShareButtonClickedDelegate
- (void)ButtonClicked {
  NSInteger x = arc4random() % 100;
  NSLog(@"原生事件%ld",x);
// 将onButtonClicked事件导出
  _bt.onButtonClicked(@{@"randomValue": [NSNumber numberWithInteger:x]});
}

下面我们在js文件中处理:
同样,在参数中添加上onButtonClicked。

ZKShareButton.js

//按钮点击事件onButtonClicked:PropTypes.func,

添加好之后,就可以调用了,调用如下:

onButtonClicked={(event) => { console.log('React事件' + event.nativeEvent.randomValue);}}

结果显示:

[连接]
(http://bbs.reactnative.cn/topic/2452/react-native%E5%8E%9F%E7%94%9Fui%E5%B0%81%E8%A3%85%E4%BB%A5%E5%8F%8A%E4%BA%8B%E4%BB%B6%E5%A4%84%E7%90%86)

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

推荐阅读更多精彩内容