React Native有什么UIafinal框架使用详解可以使用吗

尊重版权,未经授权不得转载
本文来自:江清清的技术专栏()
今天我们继续来看一下封装原生UI组件封装给React Native前端进行调用,不过当前文章所讲只是用于Android部分开发,后面会继续更新适配iOS开发的教程。
刚创建的React Native技术交流4群(),欢迎各位大牛,React Native技术爱好者加入交流!同时博客右侧欢迎微信扫描关注订阅号,移动技术干货,精彩文章技术推送!
在现在做App的开发中,其实已经有成千上万的原生UI控件用在App开发中了,其中一些是平台自带的,另外一些可能是第三方库的,也有一些可能是你自己封装或者收藏的。相信大家看我的博客看到现在也学习了React Native中的很多组件,没错这些是React Native给我们封装的,例如:ScrollView和TextInput组件,但是也由于开发精力有限不可能封装所有的组件。而且可能你为自己的App也开发相关的组件了。但是特别好的是,在React Native应用开发中我们可以很方便的封装组件并且把他们移植到我们应用程序中。
今天我们来进行讲解一下如何比较方便的进行封装一个原生的组件,不过该文章只是适配Android平台啦。如果你之前已经有Android开发的经验,那么本文就看起来非常容易啦。下面主要我们进行封装实现React Native核心库中的ImageView组件。
(二)ImageView实例
下面我们正式来看一下如果要实现在JavaScript中进行使用ImageView需要做哪些步骤方法。
原生视图View需要被ViewManager或者更加简单的SimpleViewMagner的子类进行创建和管理。在当前场景中最好创建一个继承自SimpleViewManger的子类,因为它提供更加通用简单的属性例如:background color(背景色),opacity(透明度),FlexBox layout(flexbox布局)
这些创建的子类本质上都是单例的,在React Native中该只会为管理器创建唯一一个实例。然后把原生的视图给NativeViewHierarchyManager进行管理,该会进行代理当视图需要进行设置或者更新相关属性的时候进行回调。ViewManager类也会进行代理所有视图,并给JavaScript进行发送相关的事件。
创建一个视图的步骤如下:
2.1.创建一个ViewManager子类
2.2.实现createViewInstance方法
2.3.使用@ReactProp(或者@ReactPropGroup)进行注解视图的属性方法
2.4.在应用包的createViewManagers方法中进行注册视图管理类
2.5.实现JavaScript模块
[注意].本文章中所用的例子在官方的源代码中的分布如下:
(三)创建ViewManager子类
在本实例中,我们创建一个ReactImageManager视图管理器,该是继承自SimpleViewMangaer&ReactImageView&类。ReactImageView是视图管理进行管理的,该为一个自定义的原生视图。当前创建的类中必须实现一个getName方法,该方法返回的名字用于该在JavaScript中进行调用。下面我们看一下具体的实例:
* 当前类注释:
* 项目名:android
* 包名:com.nativeuicomponentsdemo
* 作者:江清清 on 16/4/29 20:36
* 公司:江苏中天科技软件技术有限公司
public class ReactImageManager extends SimpleViewManager&ReactImageView& {
public static final String REACT_CLASS="RCTImageView";
public String getName() {
return REACT_CLASS;
(四)实现createViewInstance方法
视图会通过createViewInstance方法进行创建,同时视图会被初始化成默认状态。然后视图属性会通过updateView方法进行更新。具体代码如下:
protected ReactImageView createViewInstance(ThemedReactContext reactContext) {
return new ReactImageView(reactContext, Fresco.newDraweeControllerBuilder(),mCallerContext);
(五)使用@ReactProp(或者@ReactPropGroup)注解相关方法对外可以被调用设置属性
如果需要对外提供方法给JavaScript进行调用,那么该需要设置方法使用@ReactProp(或者@ReactPropGroup)进行注解。该设置调用的方法的第一个参数为需要修改设置属性的具体事例,第二个参数为需要设置的属性值。该被注解的方法的返回值必须为void,而且方法的访问权限必须为public。其中在JavaScript前端获取属性的类型由被注解的方法的第二个参数的类型来进行决定。支持的类型为:boolean,int,float,String,Boolean,Integer,ReadableArray,ReadableMap。
使用@ReactProp注解,该注解中必须包含一个字符串类型的属性name,该参数的值指定了在JavaScript端进行调用的属性名称。
除了name属性之后,@ReactProp注解还能接收其他一些属性例如:defaultBoolean,defaultInt,defaultFloat。这些参数必须对应基础的数据类型(boolean,int,float),但是当对应的属性被删除或者不设置,会使用null作为默认值的
注意:如果使用@ReactPropGroup进行注解,那么该和@ReactProp还是有一些不同点的,具体可以查看@ReactPropGroup注解类的相关文档查看。我们来看一下官方的注解的方法代码:
// In JS this is Image.props.source.uri
@ReactProp(name = "src")
public void setSource(ReactImageView view, @Nullable String source) {
view.setSource(source, mResourceDrawableIdHelper);
// In JS this is Image.props.loadingIndicatorSource.uri
@ReactProp(name = "loadingIndicatorSrc")
public void setLoadingIndicatorSource(ReactImageView view, @Nullable String source) {
view.setLoadingIndicatorSource(source, mResourceDrawableIdHelper);
@ReactProp(name = "borderColor", customType = "Color")
public void setBorderColor(ReactImageView view, @Nullable Integer borderColor) {
if (borderColor == null) {
view.setBorderColor(Color.TRANSPARENT);
view.setBorderColor(borderColor);
@ReactProp(name = "overlayColor")
public void setOverlayColor(ReactImageView view, @Nullable Integer overlayColor) {
if (overlayColor == null) {
view.setOverlayColor(Color.TRANSPARENT);
view.setOverlayColor(overlayColor);
@ReactProp(name = "borderWidth")
public void setBorderWidth(ReactImageView view, float borderWidth) {
view.setBorderWidth(borderWidth);
(六)进行注册ViewManager
原生代码最后一步就是进行注册ViewManager到应用中,该步骤和前面原生模块封装相类似,唯一的不同,当前是注册在createViewManagers方法,官方代码如下:
public List&ViewManager& createViewManagers(
ReactApplicationContext reactContext) {
return Arrays.&ViewManager&asList(
new ReactImageManager()
(七)实现JavaScript模块
下面是最后一步是创建JavaScript模块,用来进行定义Java和JavaScript之间的接口层。大部分的功能都是通过React底层的Java和Javas进行完成,下面就是需要使用propTypes属性进行设置属性的类型。
// ImageView.js
import { PropTypes } from 'react';
import { requireNativeComponent } from 'react-native';
var iface = {
name: 'ImageView',
propTypes: {
src: PropTypes.string,
borderRadius: PropTypes.number,
resizeMode: PropTypes.oneOf(['cover', 'contain', 'stretch']),
module.exports = requireNativeComponent('RCTImageView', iface);
requireNativeComponent会接收两个参数,第一个参数是代码视图的名字(也是之前我们getName方法返回的名称),第二个参数表示描述信息设置的对象。当前对象的name的值必须设置恰当,因为该值会在调试中进行打印。该对象还需要进行声明propTypes字段,用来反映原生视图。同时propTypes对象可以用来检查用户使用的原生视图的正确与否。
[注意].如果你需要JavaScript组件可以做更多的事情,而不仅仅为设置名称和propTypes,例如可以进行处理一些自定义的事件。那么你可以通过一个普通的React组件进行封装原生组件,那么requireNativeComponent的第二个参数就可以传入封装的组件而不是iface了。这些你可以在下面MyCustomView例子中看到。
看了上面的内容,相信大家已经对于封装原生视图并且通过前端JavaScript进行调用以及比较熟悉了,但是如果处理来自用户的事件呢?例如缩放和拖动呢?当一个原生代码的事件发生的时候,该会影响到JavaScript层的视图,该两端通过getId()方法进行相关联。官方代码如下:
class MyCustomView extends View {
public void onReceiveNativeEvent() {
WritableMap event = Arguments.createMap();
event.putString("message", "MyMessage");
ReactContext reactContext = (ReactContext)getContext();
reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
"topChange",
上面的事件名称"topChange"将会映射到onChange回调方法中(映射关系在UIManagerModuleConstants.java中),该回调方法会被原始事件调用,通过我们在封装的组件中做一个比较简单的API接口进行调用。
// MyCustomView.js
class MyCustomView ponent {
constructor() {
this._onChange = this._onChange.bind(this);
_onChange(event: Event) {
if (!this.props.onChangeMessage) {
this.props.onChangeMessage(event.nativeEvent.message);
render() {
return &RCTMyCustomView {...this.props} onChange={this._onChange} /&;
MyCustomView.propTypes = {
* Callback that is called continuously when the user is dragging the map.
onChangeMessage: React.PropTypes.func,
var RCTMyCustomView = requireNativeComponent(`RCTMyCustomView`, MyCustomView, {
nativeOnly: {onChange: true}
注意看上面的属性nativeOnly,有时候你那边有一些被注解对外提供的特殊的属性,但是又不想把该属性变成React 组件封装的属性。例如:switch有一个onChange方法专门处理原生的事件,然后我们在进行封装该组件的时候使用onValueChange作为处理事件的回调方法。该方法被调用的时候会带上switch的相关状态信息,这样的话你可能不希望原生专用的属性出现在封装的组件的API之中,也就不希望把它放到propTypes里。可是如果你不放的话,又会出现一个报错。解决方案就是带上nativeOnly属性即可。
(九)最后总结
今天我们看了一下封装原生UI组件封装给React Native前端进行调用。当前所讲解内容适配Android开发。大家有问题可以加一下群React Native技术交流4群().或者底下进行回复一下。
尊重原创,未经授权不得转载:From Sky丶清() 侵权必究!
关注我的订阅号(codedev123),每天分享移动开发技术(Android/IOS),项目管理以及博客文章!(欢迎关注,第一时间推送精彩文章)
关注我的微博,可以获得更多精彩内容
在线用户: 5今日访问: 32昨日访问: 7,022累计访问: 6,496,114React Native有什么UI框架可以使用吗_百度知道
色情、暴力
我们会通过消息、邮箱等方式尽快将举报结果通知您。
React Native有什么UI框架可以使用吗
我有更好的答案
flex Apache基金会今天发布了Flex 4.8版本,这是Adobe将Flex捐献给Apache基金会后发布的第一个版本。 需要注意的是,Flex目前还在孵化阶段,还不是Apache...天津众
维ui设计提供
采纳率:79%
为您推荐:
其他类似问题
您可能关注的内容
换一换
回答问题,赢新手礼包赞助商链接
Facebook提供了一种编写原生移动应用的效果的框架,称为:,你可以使用Javascript编写可媲美原生iOS或安卓组件的效果。James Long在过去几个月研究学习了Ember, Angular, 和 React,得到了很多Web组件的思想,这些框架都是以不同方式解决类似的问题,有些是冲突,有些是可和谐相处的。James Long主要关心数据绑定和组件化componentizing UI,在研究了上面这些技术框架后,他认为提供了最好的解决方案。James Long在一文中描述了如何使用React Native在浏览器实现3D等原生应用程序才能开发的效果。React Native还没有完全开源,Facebbook正在进行清理代码等准备工作,他们应该会更快地开源。关于跨平台原生应用目前主要由JavaScript. Titanium, PhoneGap驱动,这些项目都有一个短处,要么你将Web应用包装在一个Web浏览器中,要么他们试图模仿HTML/CSS,然后,你换可以直接和原生对象交互,但是这容易造成很大性能问题,React Natice实际在单独线程实现布局layout,这样主线程是自由的,能够聚焦一些平滑的动画等。React Native使用JavaScriptCore 在iOS中运行Javascript,最重要部分是它以单独线程运行Javascript(Titanium也是这么做),你能使用Javascript编写组件,就像你在使用React.js一样,除了不使用div和a,而是使用View和Text,你能得到React所有构建UI的组合优点。React Native会获取你的UI然后发送少量的数据到主线程,使用原生组件来渲染界面,View是一个UIView,最精彩的是你不必关心更新UI,你只要基于一些状态声明渲染即可,React会使用不同算法计算你的改变和实际界面之间的差别,然后只发送这种差别数据到实际界面进行渲染。(注:这是React.js最核心的一部分,体现效果是速度性能快)编写原生UI从来都不是很容易,而使用JS编写动画不会有性能问题,因为JS运行在单独线程。该文展示了一个使用React Native编写的OpenGL 3D应用:实现代码也很简单,试图渲染部分:var ObjList = React.createClass({
// a few methods clipped....
selectModel: function(file) {//调用Objective-C方法
controller.loadMesh(file);
renderRow: function(file) {
return View(
TouchableHighlight(
{ onPress: () => this.selectModel(file),
underlayColor: 'rgba(0, 0, 0, .6)' },
Text({ style: { height: 30, color: 'white' }}, file)
render: function() {
var source = this.getDataSource(this.props.files);
return ListView({
style: { flex: 1 },
renderRow: this.renderRow,
dataSource: source
很期待这个技术
赞助商链接
赞助商链接
最佳分辨率
OpenSource
Code & 2002-20深入浅出 React Native:使用 JavaScript 构建原生应用(上)
我的图书馆
深入浅出 React Native:使用 JavaScript 构建原生应用(上)
(点击上方蓝字,可快速关注我们)
数月前,Facebook 对外宣布了正在开发的 React Native 框架,这个框架允许你使用 JavaScript 开发原生的 iOS 应用——就在今天,Beta 版的仓库释出了!
基于 PhoneGap 使用 JavaScript 和 HTML5 开发 iOS 应用已经有好几年了,那 React Native 有什么牛的?
React Native 真的很牛,让大家兴奋异常的主要原因有两点:
可以基于 React Native使用 JavaScript 编写应用逻辑,UI 则可以保持全是原生的。这样的话就没有必要就 HTML5 的 UI 做出常见的妥协;
React 引入了一种与众不同的、略显激进但具备高可用性的方案来构建用户界面。长话短说,应用的 UI 简单通过一个基于应用目前状态的函数来表达。
React Native 的关键就是,以把 React 编程模式的能力带到移动开发来作为主要目标。它的目标不是跨平台一次编写到处执行,而是一次学习跨平台开发。这个是一个非常大的区别。这篇教程只介绍 iOS 平台,不过你一旦掌握了相关的概念,就可以应用到 Android 平台,快速构建 Android 应用。
如果之前只用过 Objective-C 或者 Swift 写应用的话,你很可能不会对使用 JavaScript 来编写应用的愿景感到兴奋。尽管如此,作为一个 Swift 开发者来说,上面提到的第二点应该可以激起你的兴趣!
你通过 Swift,毫无疑问学习到了新的更多有效的编码方法和技巧,鼓励转换和不变性。然而,构建 UI 的方式还是和使用 Objective-C 的方式一致。仍然以 UIKit 为基础,独断专横。
通过像 virtual DOM 和 reconciliation 这些有趣的概念,React 将函数式编程直接带到了 UI 层。
这篇教程将带着你一路构建一个 UK 房产搜索应用:
如果你之前一点 JavaScript 都没写过,别担心。这篇教程带着你进行一步一步进行编码。React 使用 CSS 属性来定义样式,一般比较容易读也比较容易理解。但是如果你想了解更多的话,可以去看看 Mozilla Developer Network reference,很不错的。
想要学习更多,继续往下读!
React Native 框架托管在 GitHub 上。你可以通过两种方式获取到它:使用 git 克隆仓库,或者下载一个 zip 压缩包文件。如果你的机器上已经安装了 React Native,在着手编码前还有其他几个因素需要考虑。
React Native 借助 Node.js,即 JavaScript 运行时来创建 JavaScript 代码。如果你已经安装了 Node.js,那就可以上手了。
首先,使用 Homebrew 官网提供的指引安装 Homebrew,然后在终端执行以下命令:
brew install node
接下来,使用 homebrew 安装 watchman,一个来自Facebook 的观察程序:
brew install watchman
通过配置 watchman,React 实现了在代码发生变化时,完成相关的重建的功能。就像在使用 Xcode 时,每次保存文件都会进行一次创建。
React Native 有很多的依赖,需要在运行之前安装好。在 React Native 文件目录下打开一个终端,执行下面代码:
npm install
这里通过 Node 包管理器抓取到项目的所有依赖;功能上和 CocoaPods 或者 Carthage 类似。成功执行该命令后,你会发现一个 node_modules 文件夹被创建,包含了各种外部依赖。
最后,启动开发服务器。在刚才打开的终端中,执行下面命令:
执行上面命令,你会看到:
$ npm start
& react-native@0.1.0 start /Users/colineberhardt/Projects/react-native
& ./packager/packager.sh
===============================================================
| Running packager on port 8081.
| Keep this packager running while developing on any JS
| projects. Feel free to close this tab and run your own
| packager instance if you prefer.
| /facebook/react-native
===============================================================
React packager ready.
就这样简单,准备开始!脚本在终端继续执行,我们继续。
至此,我推荐尝试一个 React Native 示例来测试配置项。在 react-native/Examples/Movies 文件夹下打开项目,然后创建并且运行它,确保你可以正确地发布这个 Movies 应用。
注意:在进入编码工作之前,还有最后一件事 —— 在这个教程中,你需要编写大量的 JavaScript 代码,Xcode 并非是最好的工具!我使用 Sublime Text,一个价格合理且应用广泛的编辑器。不过,atom,brackets 或者其他轻量的编辑器都能胜任这份工作。
React Native 你好
在开始“搜房App”之前,先来个简单的 Hello World App 热热身。在这一节里,你将会使用到一些组件。
下载起始项目,解压缩到react-native/Examples目录中。解压完成后,在Xcode中打开 PropertyFinder 项目,不要直接运行这个项目,还需要加上一些JS!
在编辑器中打开 PropertyFinderApp.js,将下面这行代码加到文件的开头位置:
'use strict';
这行代码是用于开启 Strict Mode,Strict mode的错误处理可以有所提高,JavaScript的一些语言缺陷也可以避免。简而言之就是,JavaScript在这种模式下工作地更好!
注意:想要研究一下 Strict Mode 的朋友,我会推荐你阅读 Jon Resig 的文章:“ECMAScript 5 Strict Mode, JSON, and More”
然后,加上这一行:
var React = require('react-native');
这句代码是将 react-native 模块加载进来,并将它赋值给变量 React 的。React Native 使用同 Node.js 相同的模块加载方式:require,这个概念可以等同于 Swift 中的“链接库”或者“导入库”。
注意:想要了解更多关于 JavaScript 模块的知识,我推荐阅读 Addy Osmani 写的这篇文章。
在 require 语句的下面,加上这一段:
var styles = React.StyleSheet.create({
color: 'black',
backgroundColor: 'white',
fontSize: 30,
margin: 80
以上代码定义了一段应用在 “Hello World” 文本上的样式。如果你曾接触过Web开发,那你很可能已经发现了:React Native 使用的是 CSS 来定义应用界面的样式。
现在我们来关注应用本身吧!依然是在相同的文件下,将以下代码添加到样式代码的下面:
class PropertyFinderApp ponent {
render() {
return React.createElement(React.Text, {style: styles.text}, "Hello World!");
是的,奏是 JavaScript class!
类 (class) 是在ES6中被引入的,纵然JavaScript一直在进步,但Web开发者受困于兼容浏览器的状况中,不能怎么使用JS的新特性。React Native运行在JavaScriptCore中是,也就是说,你可以使用JS的新特性啦,完全不用担心兼容什么的呢。
注意:如果你是一名 Web 开发者,我百分百鼓励你要使用现代的JavaScript,然后使用像 Babel 这样的工具生成兼容性的 JavaScript,用于支持兼容性不好的老浏览器。
PropertyFinderApp 继承了 ponent(React UI的基础模块)。组件包含着不可变的属性,可变的状态变量以及暴露给渲染用的方法。这会你做的应用比较简单,只用一个渲染方法就可以啦。
React Native 组件并不是 UIKit 类,它们只能说是在某种程度上等同。框架只是将 React 组件树转化成为原生的UI。
最后一步啦,将这一行加在文件末尾:
React.AppRegistry.registerComponent('PropertyFinderApp', function() { return PropertyFinderApp });
AppRegistry 定义了App的入口,并提供了根组件。
保存 PropertyFinderApp.js,回到Xcode中。确保 PropertyFinder 规划(scheme)已经勾选了,并设置了相应的 iPhone 模拟器,然后生成并运行你的项目。几秒之后,你应该就可以看到 “Hello World” 应用正在运行了:
这个JavaScript应用运行在模拟器上,使用的是原生UI,没有任何内嵌的浏览器哦!
还不相信这是真的?:] 那打开你的 Xcode,选择 Debug\View Debugging\Capture View Hierarchy,你看 native view hierarchy 中都没有 UIWebView,就只有一个原生的view!:]
你一定很好奇其中的原理吧,那就在 Xcode 中打开 AppDelegate.m,接着找到 application:didFinishLaunchingWithOptions:这个方法构建了 RCTRootView 用于加载 JavaScript 应用以及渲染最后的视图的。
当应用开始运行的时候,RCTRootView将会从以下的URL中加载应用:
http://localhost:8081/Examples/PropertyFinder/PropertyFinderApp.includeRequire.runModule.bundle
重新调用了你在运行这个App时打开的终端窗口,它开启了一个 packager 和 server 来处理上面的请求。
在 Safari 中打开那个 URL;你将会看到这个 App 的 JavaScript 代码。你也可以在 React Native 框架中找到你的 “Hello World” 代码。
当你的App开始运行了以后,这段代码将会被加载进来,然后 JavaScriptCore 框架将会执行它。在 Hello World 的例子里,它将会加载 PropertyFinderApp 组件,然后构建出原生的 UIKit 视图。关于这部分的内容,后文里会再详细解释的。
你好 JSX 的世界
你当前的应用程序会使用 React.createElement 来构建应用 UI ,React会将其转换到原生环境中。在当前情况下,你的JavaScript代码是完全可读的,但一个更复杂的 UI 与嵌套的元素将迅速使代码变成一大坨。
确保应用程序仍在运行,然后回到你的文本编辑器中,编辑 PropertyFinderApp.js 。修改组件 render 方法的返回语句如下:
return &React.Text style={styles.text}&Hello World (Again)&/React.Text&;
这是 JSX ,或 JavaScript 语法扩展,它直接在你的 JavaScript 代码中混合了类似 HTML 的语法;如果你是一个 web 开发人员,应该对此不陌生。在本篇文章中你将一直使用 JSX 。
把你的改动保存到 PropertyFinderApp.js 中,并返回到模拟器。按下 Cmd + R ,你将看到你的应用程序刷新,并显示更新的消息 “Hello World(again)”。
重新运行一个 React Native 应用程序像刷新 web 浏览器一样简单!:]
因为你会使用相同的一系列 JavaScript 文件,您可以让应用程序一直运行,只在更改和保存 PropertyFinderApp.js 后刷新即可
注意:如果你感到好奇,可以看看你的“包”在浏览器中,JSX被转换成什么。
这个 “Hello World” 已经够大家玩耍了,是时候构建实际的应用程序了!
我们的房产查找应用使用标准的栈式导航,基于 UIKit 的 navigation controller。现在正是添加的时候。
在 index.ios.js 文件中,把 PropertyFinderApp 重命名为HelloWorld:
class HelloWorld ponent {
“Hello World” 这几个字你还需要让它显示一会儿,但它不再是应用的根组件了。
接下来,在 HelloWorld 这个组件下面添加如下这个类:
class PropertyFinderApp ponent {
render() {
&React.NavigatorIOS
style={styles.container}
initialRoute={{
title: 'Property Finder',
component: HelloWorld,
构造一个 navigation controller,应用一个样式,并把初始路由设为 Hello World 组件。在 Web 开发中,路由就是一种定义应用导航的一种技术,即定义页面——或者说是路由——与 URL 的对应关系。
在同一个文件中,更新样式定义,包含如下 container 的样式:
var styles = React.StyleSheet.create({
color: 'black',
backgroundColor: 'white',
fontSize: 30,
margin: 80
container: {
在随后的教程中会告诉你 flex: 1 是什么意思。
回到模拟器,Cmd+R,看看新 UI 的样子:
这就是包含了 root view 的 navigation controller,目前 root view 就是 “Hello World”。很棒——应用已经有了基础的导航结构,到添加真实 UI 的时候了。
创建搜索页
在项目中添加一个新文件,命名为 SearchPage.js,然后将其放在PropertyFinderApp.js 所在目录下。在文件中添加下面代码:
'use strict';
var React = require('react-native');
StyleSheet,
TextInput,
TouchableHighlight,
ActivityIndicatorIOS,
你会注意到,位于引入 react-native 所在位置的前面有一个严格模式标识,紧接着的声明语句是新知识。
这是一种解构赋值,准许你获取对象的多个属性并且使用一条语句将它们赋给多个变量。结果是,后面的代码中可以省略掉 React 前缀;比如,你可以直接引用 StyleSheet ,而不再需要 React.StyleSheet。解构同样适用于操作数组,更多细节请戳这里。
继续在 SearchPage.js 文件中添加下面的样式:
var styles = StyleSheet.create({
description: {
marginBottom: 20,
fontSize: 18,
textAlign: 'center',
color: '#656565'
container: {
padding: 30,
marginTop: 65,
alignItems: 'center'
同样,以上都是标准的 CSS 属性。和 Interface Builder 相比,这样设置样式缺少了可视化,但是比起在 viewDidLoad() 中逐个设置视图属性的做法更友好!
只需要把组件添加到样式声明的前面:
class SearchPage extends Component {
render() {
&View style={styles.container}&
&Text style={styles.description}&
Search for houses to buy!
&Text style={styles.description}&
Search by place-name, postcode or search near your location.
render 很好地展示出 JSX 以及它表示的结构。通过这个样式,你可以轻易地描绘出组件 UI 的结构:一个容器,包含两个 text 标签。
最后,将下面的代码添加到文件末尾:
module.exports = SearchP
这可以 export SearchPage 类,方便在其他文件中使用它。
下一步是更新应用的路由,以初始化路由。
打开 PropertyFinderApp.js,在文件顶部紧接着上一个 require 语句的位置添加下面代码:
var SearchPage = require('./SearchPage');
在 PropertyFinderApp 类的 render 函数内部,通过更新 initialRoute 来引用最新添加的页面,如下:
component: SearchPage
此时,如果你愿意则可以移除 HelloWorld 类以及与它相关联的样式。你不在需要那段代码了。
切换到模拟器,按下 Cmd+R 查看新的 UI:
使用 Flexbox 定义外观
现在,你已经看到了用基本的 CSS 属性来控制外间距(margin),内间距(padding)还有颜色(color)。不过,可能你还不太了解要如何使用伸缩盒(flexbox),flexbox 是最近新加入 CSS 规范,用它就能很便利地布局界面。
React Native 用 css-layout(这是一个用 JavaScript 实现flexbox标准然后编译成 C(iOS平台)或者Java(Android平台)的库)。
Facebook把这个项目单独出来实在太正确了,这样可以编译成多种语言,促进更多新颖的应用的发展,比如flexbox layout to SVG。
在你的App中,容器(container)默认地是纵向布局,也就是说在它的子元素将会竖直地排列,像这样:
这被称为主轴 (main axis),它的方向可以是竖直的也可以是水平的。
每一个子元素在竖直方向上的位置是由它的margin,height和padding共同决定的。容器的 alignItems 属性也要设置成 center,这个属性可以控制子元素在十字轴上的位置。在这里,它实现了居中对齐的文本。
好啦,现在我们把输入框和按钮加上去吧。打开 SearchPage.js,将下面的代码插入第二个 Text 元素的后面:
&View style={styles.flowRight}&
&TextInput
style={styles.searchInput}
placeholder='Search via name or postcode'/&
&TouchableHighlight style={styles.button}
underlayColor='#99d9f4'&
&Text style={styles.buttonText}&Go&/Text&
&/TouchableHighlight&
&TouchableHighlight style={styles.button}
underlayColor='#99d9f4'&
&Text style={styles.buttonText}&Location&/Text&
&/TouchableHighlight&
现在你已经加上了两个最高等级的视图(top-level view),一个视图包含了文本输入框和一个按钮,还有一个视图内只有一个按钮。在后文中你会看到,它们的样式是什么样的。
接着,添加上对应的样式:
flowRight: {
flexDirection: 'row',
alignItems: 'center',
alignSelf: 'stretch'
buttonText: {
fontSize: 18,
color: 'white',
alignSelf: 'center'
height: 36,
flexDirection: 'row',
backgroundColor: '#48BBEC',
borderColor: '#48BBEC',
borderWidth: 1,
borderRadius: 8,
marginBottom: 10,
alignSelf: 'stretch',
justifyContent: 'center'
searchInput: {
height: 36,
padding: 4,
marginRight: 5,
fontSize: 18,
borderWidth: 1,
borderColor: '#48BBEC',
borderRadius: 8,
color: '#48BBEC'
要注意格式问题:每一个样式都是用逗号分隔开的,所以别忘了在container 选择器后面还要加上一个逗号。
以上的样式将会应用在你刚刚加上的输入框和按钮上。
现在返回到模拟器,然后按下 Cmd+R 刷新界面:
文本区域和 ’Go’ 按钮在同一行,不需要显式地定义两个组件的宽度,你只需要将它们放在同一个容器中,加上 flexDirection:'row' 样式,再定义好它们的 flex 值。文本区域是 flex:4,按钮则是 flex:1,这说明两者的宽度比是4:1。
大概你也发现了,你的“按钮”其实并不是按钮!:] 使用了 UIKit 后,按钮更倾向于是可以轻碰(tap)的标签(label),所以 React Native 团队决定直接在 JavaScript 中构建按钮了。所以你在 App 中使用的按钮是 TouchableHighlight,这是一个 React Native 组件,当轻碰 TouchableHighlight 时,它会变得透明从而显示出衬底的颜色(也就是按钮下层的组件颜色)。
搜索界面的最后一步就是加上一张图片.你可以从这里下载我们用的图片素材并解压。
在Xcode中打开Images.xcassets文件,点击加号添加一个新的图片集。然后将图片素材拖进正确的“区间”:
你需要重启应用才能让图片生效。
将以下代码添加到 TouchableHighlight 组件后面,它将用于“获取位置”按钮:
&Image source={require('image!house')} style={styles.image}/&
现在再样式表的最后加上图片对应的样式,别忘了给原样式中最后一个加上逗号哦:
width: 217,
height: 138
require('image!house') 语句用于确定在你应用的asset目录下的图片资源,在 Xcode 中,如果你的打开了 Images.xcassets,你会看到一个“房屋”的图标,正是上面代码中引用到的。
返回到模拟器,Cmd+R刷新UI:
注意:如果你这会没有看到“房屋”图片,取而代之的是一张“找不到资源”的图片,尝试重启packager(也就是在终端里输入 npm start 命令)。
现在你的应用看起来挺不错的啦,不过它还少了点功能。接下来你的任务就是给它加上点状态,让它执行一些操作。
原文出处:Colin Eberhardt
译文出处:前端外刊评论
链接:/FrontendMagazine/
馆藏&99439
TA的最新馆藏
喜欢该文的人也喜欢}

我要回帖

更多关于 afinal框架使用详解 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信