返回介绍

尝试创建自定义视图

发布于 2025-04-26 18:09:27 字数 5460 浏览 0 评论 0 收藏 0

我们将要创建一个简单地继承自 UIView 的原生视图,在视图中画一个正方形,然后通过 JavaScript 的 JSX 模板的 isRed 属性控制正方形的颜色是否显示成红色。我们可以在 JSX 模板中这样使用它:

<MyCustomView style= {{width:10, height:10}} isRed = {this.state.
    shouldBeRed} />

首先我们创建自定义视图,在 Xcode 菜单中选择新建 New→File,然后选择“Cocoa Touch Class”。命名为 MyCustomView,设置基类为 UIView。

然后,我们创建视图管理器(View Manager),使用 Xcode 创建另一个类,但这次把它命名为 MyCustomViewManager,并设置基类为 RCTViewManager。 [2]

在我们刚刚创建的 MyCustomViewManager.m 文件中,我们需要添加一个视图方法来返回自定义视图。

- (UIView*)view
{
    MyCustomView * theView;
    theView = [[MyCustomView alloc] init];
    return theView;
}

我们希望允许 isRed 属性(接下来会在自定义视图中添加)被设置。要做到这一点,我们需要使用 React Native 定义在 RCTViewManager 头文件中的一个名为 RCT_EXPORT_VIEW_PROPERTY 的宏。我们可以在上文定义视图方法的代码前面添加下面这行代码,它绑定了 JSX 和原生视图的名为 isRed 的同名属性:

RCT_EXPORT_VIEW_PROPERTY(isRed, BOOL);

为了使用自定义视图和一些 UIKit 的方法,我们还需要在当前文件头部引入一些头文件:

#import "MyCustomView.h"
#import <UIKit/UIKit.h>

现在,我们在 MyCustomView.m 文件中添加 isRed 属性的设置器(setter)。

#import "MyCustomView.h"
@implementation MyCustomView
{
    UIColor *squareColor;
}
- (void)setIsRed:(BOOL)isRed
{
    squareColor = (isRed) ? [UIColor redColor] : [UIColor
        greenColor];
    [self setNeedsDisplay];
}
- (void)drawRect:(CGRect)rect
{
    [squareColor setFill];
    CGContextFillRect(UIGraphicsGetCurrentContext(), rect);
}

以上就是我们在 Objective-C 端需要处理的所有代码。下面我们研究怎样才能把它和 React Native 的 JavaScript 代码关联起来。createReactIOSNativeComponentClass 方法可以做这件事。同时,我们需要再一次指定我们可以设置的属性(这里是 isRed)。

现在,我们可以像使用一个常规的 React Native 视图组件一样使用 MyCustomView 了。使用它更新一下 render 方法:

render: function() {
    return (
        <View style={styles.container}>
            <Text>Red one</Text>
            <MyCustomView style={{width: 10, height: 10}} isRed={
                true}/>
            <Text>Not red one</Text>
            <MyCustomView style={{width: 10, height: 10}} isRed={
                false}/>
        </View>
    );
}

至此,我们完成了 React Native 调用自定义 Objective-C 视图的操作。

下面是自定义视图的源码:

MyCustomView.h



#import <UIKit/UIKit.h>

@interface MyCustomView : UIView

@property (nonatomic) BOOL isRed;

@end

MyCustomView.m



#import "MyCustomView.h"

@implementation MyCustomView
{
  UIColor *squareColor;
}

- (void)setIsRed:(BOOL)isRed
{
  squareColor = (isRed) ? [UIColor redColor] : [UIColor greenColor
      ];
  [self setNeedsDisplay];
}

- (void)drawRect:(CGRect)rect {
  [squareColor setFill];
  CGContextFillRect(UIGraphicsGetCurrentContext(), rect);
}
@end

MyCustomViewManager.h



#import "RCTViewManager.h"

@interface MyCustomViewManager : RCTViewManager

@end

MyCustomViewManager.m



#import "MyCustomViewManager.h"
#import "MyCustomView.h"
#import <UIKit/UIKit.h>

@implementation MyCustomViewManager

RCT_EXPORT_MODULE();

RCT_EXPORT_VIEW_PROPERTY(isRed, BOOL);

- (UIView *)view
{
  MyCustomView *theView;
  theView = [[MyCustomView alloc] initWithFrame:CGRectMake(0, 0,
      10, 10)];
  return theView;
}

@end

最后是 Demo 应用程序的 index.ios.js 文件的源码:

'use strict';

var React = require('react-native');
var {
  AppRegistry,
  StyleSheet,
  Text,
  View, 
[3]

 


} = React;

var createReactIOSNativeComponentClass =
        require('createReactIOSNativeComponentClass');

var MyCustomView = createReactIOSNativeComponentClass({
    validAttributes: {isRed: true},
    uiViewClassName: 'MyCustomView'
}); 
[4]

 



var Demo = React.createClass({
  render: function(){
    return (
      <View style={styles.container}>
        <Text>Red one</Text>
        <MyCustomView style={styles.customView} isRed={true}/>
        <Text>Not red one</Text>
        <MyCustomView style={styles.customView} isRed={false}/>
      </View>
    );
  }
});
var styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#F5FCFF',
  },
  customView: {
    width: 10,
    height: 10
  }
});

AppRegistry.registerComponent('Demo', () => Demo);

[1] 这里描述的写法已经在 React Native 4.0.3 中废弃,新的用法 requireNativeComponent 已经在文档中说明。——译者注

[2] RCTViewManager.h 是视图管理器的头文件,命名规范为:视图名称+Manager。视图名称可以加上自己的前缀,这里最好避免使用 RCT 前缀,除非你想给官方 pull request。——译者注

[3] 增加下面两行:

PropTypes,
requireNativeComponent

——译者注

[4] 以上方法在 v0.4.3 中已废弃,可改为:

var MyCustomView = React.createClass({
  propTypes: {
    isRed: true
  },
  render: function () {
    return NativeCustomView {...this.props}/>;
  }
});
var NativeCustomView = requireNativeComponent('MyCustomView', MyCustomView);

——译者注

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。