React Native - 常用组件

 

React Native - 常用组件

转至元数据结尾

  •  

转至元数据起始

本文提到的常用组件有:

  • ActivityIndicator
  • TouchableOpacity

  • FlatList

  • Image

  • RefreshControl

  • Slider

  • Switch

  • Text

  • Alert

 

ActivityIndicator

概述

显示一个圆形的加载指示器。

示例

 


运行后,动态效果图如下:

  
 

 

常用参数

animating

是否显示指示器。

  • true: 显示 (默认值)。
  • false: 不显示。

 

color

指示器的颜色 (默认灰色)。

 

size

指示器的大小。

  • 'small': 小 (默认值)。
  • 'large': 大。
  • number: 通过数字指定大小,仅支持 Android 平台。

 

hidesWhenStopped

指示器动画停止时,是否隐藏指示器 (默认为 true),仅支持 iOS 平台。

注:当 animating 和 hidesWhenStopped 同时为 false 时:

  • iOS 平台的指示器会暂停动画,但指示器本身还是可见的
  • Android 平台指示器会直接被隐藏

扩展

所谓的指示器,在 App 中可以简单的理解为 "网络加载提示视图"。

假设我们现在有一个需求,需要在 "闲鱼" App 增加一个对商品点赞的功能:

  • 用户点击 "赞" 按钮的时候发起网络请求,在请求成功后对当前点赞数加一。
  • 为了友好的用户体验,我们在发起网络请求的时候需要将按钮内容显示为 ActivityIndicator,然后在请求成功后再显示 点赞数

撸起袖子就是干

我们先来封装一个通用的 StateView 来管理 ActivityIndicator 和 点赞数 的显示控制:

./src/StateView.tsx

 

至此,配料 StateView 准备好了,我们开始炒 (write) 菜 (example-code):

./App.tsx

 


运行后,动态效果图如下:

 

注意:在实际开发中,我们应该将 App.tsx 中编写的 "点赞" 按钮封装成一个单独的组件,以便以后可能需要的代码复用。

代码解析

如果你没有学过 TypeScript 的话,可能会觉得上述的示例代码有点羞涩难懂,所以这里再针对其中 TypeScript 相关的内容做下解析。

TypeScript 语法

在 TypeScript 定义接口的语法姿势是这样的:

 

在上面的代码片段中,我们可以将接口 InterfaceName 理解成 "类型",

然后我们在声明变量 interfaceExample 的时候就通过 语法来将其类型指定为 interfaceExample

 

另外,在定义类型的时候我们除了可以使用 interface 接口关键字外,

也可以使用 type 和 typeof 关键字来定义类型别名。比如:

 


上面两个代码片段中对 InterfaceName 接口的声明是完全等价的,主要区别在于后者使用了 type 和 typeof 定义了 "类型别名"。

 

TypeScript 在 React Native 中的应用

在 @types/react/index.d.ts 中,我们可以看到 Component 的定义大致是这样的:

 
  • Component 接收两个泛型参数:P 是组件属性 Props 的类型,S 是组件状态 State 的类型。
  • 构造函数 constructor 的参数类型是 P
  • setState 方法中通过 extends of S 限定泛型参数 K 的范围,参数 state 的类型可能是一个函数类型,也可能是 S 类型或 "S 键的一部分" 类型:
    • ((prevState: Readonly<S>, props: Readonly<P>) => (Pick<S, K> | S | null))
    • (Pick<S, K> | S | null)
  • 通过 readonly 关键字指定 props 是只读的,不可修改的。同时,可修改的 state 的类型声明中,通过 Reactonly 来对 S 做了类型映射。

 

综上,我们在定义 React Native 组件的时候,可以酱紫写:

 

另外,如果你仔细看的话会发现,我们在 create 样式的时候也使用到了 interface 和泛型,这种姿势一般是这样的:

 

在定义样式时通过泛型来指定具体样式的类型,这样做的好处在于:如果我们编写样式代码时使用了不符合对应类型的属性,编辑器会进行错误提示。

比如说如果写成这样:

 

这时编辑器会提示我们,fontSize 不符合 ViewStyle 类型定义。

 

TouchableOpacity

一个可用于封装视图并可正确响应触摸操作的按钮组件。在按下的时候,封装的视图的不透明度会降低,

也就是说会更加透明一点,这个 "一点" 到底是多少则可以通过其 activeOpacity 属性进行配置。

不透明度的变化是通过把子元素封装在一个 Animated.View 中来实现的,这个动画视图会被添加到视图层级中,少数情况下有可能会影响到布局。

此组件与 TouchableHighlight 组件的区别在于并没有额外的颜色变化,适用场景一般更广一些。

示例代码

 

动态效果图如下:

 

常用属性

activeOpacity

指定封装的视图在被触摸操作激活时以多少不透明度显示 (0 到 1 之间)。默认值为 0.2。

个人感觉 0.2 的时候透明度较高了,可以封装一个全局的 Touchable 组件出来并调整为 0.8,封装全局 Touchable 组件还可以通过 "节流/防抖" 来解决快速点击导致的多次响应 onPress 事件问题。

 

常用方法

setOpacityTo((value: number), (duration: number));将本组件的不透明度设为指定值 (伴有过渡动画)。

 

FlatList

概述

FlatList 是一个高性能的、易于使用的列表组件,它有以下特性:

  • 完全跨平台
  • 支持水平布局模式
  • 可配置行组件显示或隐藏时的回调事件
  • 支持单独的头部组件 (Header)
  • 支持单独的尾部组件 (Footer)
  • 支持自定义行间分隔线
  • 支持下拉刷新
  • 支持上拉加载
  • 支持滚动到指定行 (ScrollToIndex)

如果需要分 "组/类/区" (section),可使用功能类似的 <SectionList> 组件。

简单示例

下面是使用 FlatList 的一个简单示例:

 


通过 data 属性指定数据源,再通过 renderItem 属性指定列表项绘制逻辑即可,运行后的效果图是这样的:

 

类似上述绘制 Text 组件的示例,我们来看一个有完整代码和动态效果图的:

 
  
  

注:在上面的动态图中可以看到,相同的代码在 iOS 中是可以左右滑动的,而在 Android 中则不能。如果不期望有这个特性的话可以通过 ScrollView 的一个属性 (好像是 bounces,记不太清了) 来禁用掉,因为 FlatList 有着 ScrollView 所有的属性,所以直接使用该属性即可。

复杂点儿的示例

下面是一个稍微复杂点儿的例子,演示了如何利用 PureComponent 来进一步优化性能和减少 bug 产生的可能。

如何避免不必要的渲染

在上代码前,我们先来了解两个知识点:

  • 组件 shouldComponentUpdate 机制。
  • Component 和 PureComponent 的区别。

 

shouldComponentUpdate

shouldComponentUpdate 是组件的一个钩子函数,其函数原型如下:

 

使用 shouldComponentUpdate() 可以让 React 知道当前状态或属性的改变是否不影响组件的输出,该函数默认返回 ture,即表示需要重新渲染 (返回 false 时则表示不需要)。

另外,在组件初始化渲染时或在使用 forceUpdate() 强制时该方法不会被调用。如果我们想要避免不必要的渲染,姿势大致是这样:

 

看似简单,但是在一个项目中有那么多组件,难道我们要一个一个编写代码去判断 nextState 和 this.state 里面的数据吗?

显然不用,React 提供了一个名为 PureComponent 的组件。

 

PureComponent

PureComponent 与 Component 的功能几乎完全相同,但 PureComponent 会通过 props 和 state 进行浅比较来决定是否需要重新渲染。

 


注:浅比较,比较引用是否相同;深比较,比较原值是否相等,需要递归变量两个比较对象的所有属性,不用管引用是否相同。

代码和动态效果图

 

 

  • 对于 MyListItem 组件来说,其 onPressItem 属性使用箭头函数而非 bind 的方式进行绑定,使其不会在每次列表重新 render 时生成一个新的函数,从而保证了 props 的不变性 (当然前提是 idselected和 title 也没变) ,不会触发自身无谓的重新绘制。换句话说,如果你是用 bind 来绑定 onPressItem,每次都会生成一个新的函数,导致 props 在 === 比较时返回 false,从而触发自身的一次不必要的重新绘制。
  • 给 FlatList 指定 extraData={this.state} 属性,是为了保证 state.selected 变化时,能够正确触发 FlatList的更新。如果不指定此属性,则 FlatList 不会触发更新,因为它是一个 PureComponent,其 props 在 === 比较中没有变化则不会触发更新。
  • keyExtractor 属性指定使用 id 作为列表每一项的 key。

扩展

FlatList 组件实质是基于 <VirtualizedList> 组件的封装,它继承了其所有 props (也包括 <ScrollView> 所有的),详细内容可在官方文档 API 部分找到。

此外,在使用 FlatList 时有以下注意事项:

  • 当某行滑出渲染区域之外后,其内部状态将不会保留,需自行确保有在行组件以外的地方保留了数据。
  • 本组件继承自 PureComponent 而非通常的 Component,这意味着如果其 props 在浅比较中是相等的,则不会重新渲染。所以需要检查你的 renderItem 函数所依赖的 props 数据 (包括 data 属性以及可能用到的父组件的 state),如果是一个引用类型 (Object 或者数组都是引用类型),则需要先修改其引用地址 (比如先复制到一个新的 Object 或者数组中),然后再修改其值,否则界面很可能不会刷新。
  • 为了优化内存占用同时保持滑动的流畅,列表内容会在屏幕外异步绘制。这意味着如果用户滑动的速度超过渲染的速度,则会先看到空白的内容。这是为了优化不得不作出的妥协,你可以根据自己的需求调整相应的参数,而我们 (官方) 也在设法持续改进。
  • 默认情况下每行都需要提供一个不重复的 key 属性,你也可以提供一个 keyExtractor 函数来生成 key。

FlatList 组件如果嵌套在其它同滚动方向的 FlatList 中,则不会继承 ScrollView 的 Props 。Excuse me ?...

常用属性

renderItem

 


从 data 中挨个取出数据并渲染到列表中。renderItem 属性的类型是一个返回值为 React.Element 的函数。其参数列表中除了有列表项对应的数据项 item 外,还有可能会用到的 index 和 separators 参数,可根据实际情况决定是否使用,下面是官方文档对 index 和 separators 的一个描述:

Provides additional metadata like index if you need it, as well as a more generic separators.updateProps function which let you set whatever props you want to change the rendering of either the leading separator or trailing separator in case the more common highlight and unhighlight (which set the highlighted: boolean prop) are insufficient for your use case.

  
  

示例:

 

data

为了简化起见,data 属性目前只支持普通数组。如果需要使用其他特殊数据结构,例如 immutable 数组,请直接使用更底层的 VirtualizedList 组件。

  
  

 

ItemSeparatorComponent

行与行之间的分隔线组件,不会出现在第一行之前和最后一行之后。

By default, highlighted and leadingItem props are provided. renderItem provides separators.highlight/unhighlight 

which will update the highlighted prop, but you can also add custom props with separators.updateProps.

  
  

ListEmptyComponent

列表为空时渲染该组件。可以是 React.Component,也可以是一个 render 函数,亦或者是渲染好的 Element。

  
  


ListFooterComponent

尾部组件。类似 ListEmptyComponent,该属性对应的可以是 React.Component, 也可以是一个 render 函数,亦或者是渲染好的 Element。

 

ListHeaderComponent

头部组件。类似 ListEmptyComponent,该属性对应的可以是 React.Component, 也可以是一个 render 函数,亦或者是渲染好的 Element。

 

columnWrapperStyle

如果设置了多列布局 (即将 numColumns 值设为大于 1 的整数),则可以通过该属性额外指定样式作用在每行容器上。

  
  

extraData

如果有除 data 以外的数据用在列表中 (不论是用在 renderItem 还是头部或者尾部组件中),请在此属性中指定。

同时此数据在修改时也需要先修改其引用地址 (比如先复制到一个新的 Object 或者数组中),然后再修改其值,否则界面很可能不会刷新。

  
  

getItemLayout

 

getItemLayout 是一个可选的优化,用于避免动态测量内容尺寸的开销,不过前提是你可以提前知道内容的高度。

如果你的行高是固定的,getItemLayout 用起来就既高效又简单,类似下面这样:

 

对于元素较多的列表 (几百行) 来说,添加 getItemLayout 可以极大地提高性能。

注意如果你指定了 ItemSeparatorComponent,请把分隔线的尺寸也考虑到 offset 的计算之中。

  
  

horizontal

设置为 true 则变为水平布局模式。

  
  

initialNumToRender

指定一开始渲染的元素数量,最好刚刚够填满一个屏幕,这样保证了用最短的时间给用户呈现可见的内容。

注意这第一批次渲染的元素不会在滑动过程中被卸载,这样是为了保证用户执行返回顶部的操作时,不需要重新渲染首批元素。

  
  

initialScrollIndex

开始时屏幕顶端的元素是列表中的第 initialScrollIndex 个元素, 而不是第一个元素。

如果设置了这个属性,则第一批 initialNumToRender 范围内的元素不会再保留在内存里,而是直接立刻渲染位于 initialScrollIndex 位置的元素。

需要先设置 getItemLayout 属性。

  
  

inverted

翻转滚动方向。实质是将 scale 变换设置为 -1。

  
  

 

keyExtractor

(item: object, index: number) => string;

此函数用于为给定的 item 生成一个不重复的 key。Key 的作用是使 React 能够区分同类元素的不同个体,以便在刷新时能够确定其变化的位置,减少重新渲染的开销。

若不指定此函数,则默认抽取 item.key 作为 key 值。若 item.key 也不存在,则使用数组下标。

  
  

numColumns

多列布局只能在非水平模式下使用,即必须是 horizontal={false}。此时组件内元素会从左到右从上到下按 Z 字形排列,类似启用了 flexWrap 的布局。

组件内元素必须是等高的——暂时还无法支持瀑布流布局。

  
  

onEndReached

 

当列表被滚动到距离内容最底部不足 onEndReachedThreshold 的距离时调用。

  
  

onEndReachedThreshold

决定当距离内容最底部还有多远时触发 onEndReached 回调。注意此参数是一个 "比例值" 而 "非像素单位值"。

比如说,当设置为 0.5 时则表示距离内容最底部的距离为当前列表可见长度的一半时触发。

  
  

onRefresh

 

如果设置了此选项,则会在列表头部添加一个标准的 RefreshControl 控件,以便实现 "下拉刷新" 的功能。要注意,同时在该方法触发后你需要自行正确的正确设置 refreshing 属性。

  
  

 

onViewableItemsChanged

(info: { viewableItems: array, changed: array }) => void

在可见行元素变化时调用,可见范围和变化频率等参数的配置请设置 viewabilityConfig 属性。

  
  

progressViewOffset

当需要在指定的偏移处显示加载指示器的时候,就可以设置这个值。

   
   

refreshing

在等待加载新数据时将此属性设为 true,列表就会显示出一个提示正在加载的视图。

  
  

removeClippedSubviews

对于大列表启用本属性可能可以提高性能,但在有些情况下会有 bug (比如内容无法显示),所以需要谨慎使用。

  
  

 

常用方法

scrollToEnd()

 

滚动到底部。注意,如果不设置 getItemLayout 属性的话,可能会显得有点卡。

参数:

    
    

参数 params 的有效 keys 有:

  • animated:布尔类型,决定列表滚动时是否有个动画,默认值为 true

 

scrollToIndex()

 

将位于指定位置的元素滚动到可视区的指定位置。

注意:如果不设置 getItemLayout 属性的话,无法跳转到当前渲染区域以外的位置。

参数:

    
    

参数 params 的有效 keys 有:

  • animated:布尔类型,决定列表滚动时是否有个动画,默认值为 true
  • index:number 类型,要滚动到的列表项的索引值,必填。
  • viewOffset:number 类型,用于偏移最终目标位置的固定像素数,必填。
  • viewPosition:number 类型,一个决定列表项最终目标位置的比例值,比如说:
    • 为 0 时将它滚动到屏幕顶部。
    • 为 1 时将它滚动到屏幕底部。
    • 为 0.5 时将它滚动到屏幕中央。

 

scrollToItem()

 

这个方法会顺序遍历元素,请尽可能使用 scrollToIndex 代替。

注意:类似 scrollToIndex(),如果不设置 getItemLayout 属性的话,无法跳转到当前渲染区域以外的位置。

参数:

    
    

参数 params 的有效 keys 有:

  • animated:布尔类型,决定列表滚动时是否有个动画,默认值为 true
  • item:object 类型,要滚动到的 "数据" 对应的列表项。
  • viewPosition:见 scrollToIndex 属性部分。

 

recordInteraction()

 
主动通知列表发生了一个事件,以使列表重新计算可视区域。比如说当 waitForInteractions 为 true 并且用户没有滚动列表时。
一般会在用户点击了列表项或发生了导航动作时调用。

 

flashScrollIndicators()

 

短暂地显示下滚动指示器。

 

Image

概述

Image 组件用于显示多种不同类型 (来源) 图片,包括网络图片、静态资源、临时的本地图片以及本地磁盘上的图片。

下面的例子分别演示了如何显示从本地缓存、网络甚至是以 'data:' 的 base64 uri 形式提供的图片。

注意:对于网络和 base64 数据的图片需要手动指定尺寸。

 

显示效果如下图:

另外,你也可以给图片添加 style 属性:

 

此时,显示效果就变成了这样:

 

在 Android 上支持 GIF 和 WebP 格式图片

默认情况下,Android 平台不支持显示 GIF 和 WebP 格式图片。

如有需要,可在 android/app/build.gradle 文件中根据需要手动添加以下模块:

 


Fresco 是 Facebook 开源的一款 Android 图片加载库,支持显示 GIF 和 Webp (静态和动态) 格式的图片。

常用属性

style

Image 组件的 style 属性很强大,比如说我们:

  • 可以通过其 opacity 属性来指定透明度。
  • 可以通过其 tintColor 来为所有非透明的像素指定一个颜色。
  • 可以通过其 resizeMode 来调整图片尺寸。
  • 可以通过其 transforms 属相来对图片进行变换。
  • ...

下面我们通过几个示例来玩耍下:

 

1

   
  

 

 

 
     
  

注:示例 4、5、6 在该情况下显示是完全相同的。

transform 比较有趣,我们来特别说明一下:

  • transform 接收一个转换对象数组。
  • 每个对象都指定将被转换为键的属性和在转换中使用的值。对象不应组合。
  • 每个对象使用一个键/值对。
  • 旋转 (rotate) 转换需要一个字符串,以便转换可以用度(deg)或弧度(rad)表示。例如: transform([{ rotateX: '45deg' }, { rotateZ: '0.785398rad' }])
  • 倾斜 (skew) 转换需要一个字符串,以便转换可以用度数(deg)表示。例如: transform([{ skewX: '45deg' }])

transform 接收的对象值可能有:

  • { perspective: number }
  • { rotate: string }
  • { rotateX: string }
  • { rotateY: string }
  • { rotateZ: string }
  • { scale: number }
  • { scaleX: number }
  • { scaleY: number }
  • { translateX: number }
  • { translateY: number }
  • { skewX: string }
  • { skewY: string }

transform 示例:

// 变换1:`transform: [{rotateX: '45deg'}]`
// 变换2:`transform: [{rotateY: '45deg'}]`
// 变换3:`transform: [{skewY: '45deg'}]`
// 变换4:`transform: [{rotate: '45deg'}]`
 
    
   

 

 
 
// 变换5:`transform: [{scaleX: 0.4}]`
// 变换6:`transform: [{translateX: 24}]`
// 变换7:`transform: [{skewY: '45deg'}]`
// 变换8:`transform: [{translateX: 60}, {translateY: 60}, {rotateY: '60deg'}]`
 
    
  
 
 

blurRadius

blurRadius (模糊半径):为图片添加一个指定半径的模糊滤镜,类型为 number。比如:

    
  

 

onLayout

当元素加载或者布局改变的时候调用,参数为:{nativeEvent: {layout: {x, y, width, height}}}.

 

onLoad

加载成功完成时调用此回调函数。

 

加载结束后,不论成功还是失败,调用此回调函数。

 

onLoadStart

在加载开始时回调该函数。

示例:onLoadStart={(e) => this.setState({loading: true})}

 

resizeMode

决定当组件尺寸和图片尺寸不成比例的时候如何调整图片的大小。

  • cover: 在保持图片宽高比的前提下缩放图片,直到宽度和高度都大于等于容器视图的尺寸。
    • 如果容器有 padding 内衬的话,则相应减去。
    • 这样图片完全覆盖甚至超出容器,容器中不留任何空白。
  • contain: 在保持图片宽高比的前提下缩放图片,直到宽度和高度都小于等于容器视图的尺寸。
    • 如果容器有 padding 内衬的话,则相应减去。
    • 这样图片完全被包裹在容器中,容器中可能留有空白。
  • stretch: 拉伸图片且不维持宽高比,直到宽高都刚好填满容器。
  • repeat: 重复平铺图片直到填满容器。图片会维持原始尺寸,但是当尺寸超过容器时会在保持宽高比的前提下缩放到能被容器包裹。
  • center: 居中不拉伸。

 

source

用于指定图片资源 (远程 URL 或本地文件资源)。

目前原生支持的图片格式有 pngjpgjpegbmpgif,以及:

  • webp 仅限 Android。
  • psd 仅限 iOS。
  
  

 

loadingIndicatorSource

与 source 属性类似,此属性用于指定呈现 "图片加载指示器" 的资源,会显示直到要加载的图片准备好为止,通常用于需要从网络下载图片的场景。

Can accept a number as returned by require('./image.jpg')

 

示例(在 Android 上试了好几次都没看到预期指示器效果,姿势不对?):

 


onError

当加载错误的时候调用此回调函数,参数 {nativeEvent: {error}}

 

resizeMethod

当图片实际尺寸和容器样式尺寸不一致时,决定以怎样的策略来调整图片的尺寸,仅支持 Android 平台。默认为 auto

  • auto: 使用启发式算法来在 resize 和 scale 中自动决定。
  • resize: 在图片解码之前,使用软件算法对其在内存中的数据进行修改。当图片尺寸比容器尺寸大得多时,应该优先使用此选项。
  • scale: 对图片进行缩放。和 resize 相比,scale 速度更快 (一般有硬件加速),而且图片质量更优。在图片尺寸比容器尺寸小或者只是稍大一点时,应该优先使用此选项。

 

defaultSource

在读取图片时默认显示的图片。仅限 iOS 使用。

   
   
   

注:number - 静态图片引用语法 require('./image.jpg') 所返回的资源 id。

Note:For Android, It works only on release builds, don't worry if it shows nothing on DEBUG builds.

 

onPartialLoad

如果图片本身支持逐步加载,则逐步加载的过程中会调用此方法,"逐步加载" 的具体定义与具体的标准和实现有关。

   
   

onProgress

在加载过程中不断调用,参数为 { nativeEvent: {loaded, total }}

   
   

 

常用方法

getSize()

 

在显示图片前获取图片的宽高(以像素为单位)。如果图片地址不正确或下载失败,此方法也会失败。

要获取图片的尺寸,首先需要加载或下载图片(同时会被缓存起来)。这意味着理论上你可以用这个方法来预加载图片,虽然此方法并没有针对这一用法进行优化,而且将来可能会换一些实现方案使得并不需要完整下载图片即可获取尺寸。所以更好的预加载方案是使用下面那个专门的预加载方法。

注意:此方法不能用于静态图片资源。

参数:

    
    
    
    

prefetch()

 

预加载一个远程图片(将其下载到本地磁盘缓存)。

参数:

    
    

abortPrefetch()

 

中断预加载操作。仅 Android 可用。

参数:

    
    

queryCache()

 

查询图片缓存状态。根据图片 URL 地址返回缓存状态,比如 "disk" (缓存在磁盘文件中)或是 "memory" (缓存在内存中)。

参数:

    
    

 

附录

附几个 Image 相关属性类型在 index.d.ts 中的定义:

ImageSourcePropType

 

ImageProps

 

 

RefreshControl

该组件用于 ScrollView 或 FlatList 内部,以为其添加下拉刷新的功能。

当 ScrollView 处于竖直方向的起点位置(scrollY: 0)时,下拉会触发一个 onRefresh 事件。

示例

 

 

注意:refreshing 是一个受控属性, 所以必须在 onRefresh 回调函数中设置其值为 true,否则 loading 指示器会立即停止。

使用时大致效果如下 (示例代码大致如上,故略):

  
  

常用属性

refreshing

视图是否应该在刷新时显示指示器,布尔类型,true 时表示显示。

 

onRefresh

在视图开始刷新时回调的函数,非必填。

 

colors

指定至少一种颜色用来绘制刷新指示器,类型为 <color>[],仅适用于 Android 平台。

 

enabled

指定是否要启用刷新指示器,仅适用于 Android 平台。

progressBackgroundColor

指定刷新指示器的背景色,类型为 color,仅适用于 Android 平台。

 

progressViewOffset

指定刷新指示器的垂直起始位置 (top offset),类型为 number,仅适用于 Android 平台。

 

size

指定刷新指示器的大小,具体数值可参阅 RefreshControl.SIZE,仅适用于 Android 平台。

 

tintColor

指定刷新指示器的颜色,仅适用于 iOS 平台。

 

title

指定刷新指示器下显示的文字,仅适用于 iOS 平台。

 

titleColor

指定刷新指示器下显示的文字的颜色,仅适用于 iOS 平台。

小结

从属性上来看,可以看出 RefreshControl 在两个平台上的差异比较大,属性基本也都不相同。

所以,为了使得使用简单并且保证在所有页面上下拉刷新的样式一致,通常我们会封装一个 RefreshControl 出来。

比如命名为 CustomRefreshControl,然后指定默认的 colors 和 tintColor 属性,然后暴露额外相关属性即可。

 

 

Slider

Slider 是 React Native 中一个内置的、用于在一个范围值内选择单个值的组件。

但现在官方已不推荐直接使用该组件,而是推荐使用社区维护的 react-native-community/react-native-slider 依赖库中的 Slider 组件,两者相差不大,但使用社区版的话显然更好一点。

社区版的独立于 React Native 框架本身,出现问题能够快速进行更新。

因为本文是比较久前写的了,所以使用的是内置的 Slider

示例

话不多说,先上两颗栗子。

第一颗:属性参数

 

两个平台的运行效果图分别如下:

  
 

 

 

 

 

第二颗:方法参数

 

iOS 和 Android 两个平台的效果是一致的,如下动态图:

 

常用参数

style

如果你有用 TypeScript 写过 React Native 应用的话,可以将其理解为是 ViewStyle

如果没有用过的话,则可参考 ViewStylePropTypes.js 以获取更多信息。

 


disabled

设为 true 时 Slider 不能滑动,默认为 false

 

maximumValue

Slider 的最大值,默认为 1

 

minimumTrackTintColor

"滑块" 左侧滑条的颜色值。

 

minimumValue

Slider 的最小值,默认为 0

 

onSlidingComplete

不管值是否发生了变化,当用户释放 "滑块" (结束滑动) 时都会回调该方法,释放时当前的值会作为该方法的参数。

 

onValueChange

在用户滑动 "滑块" 过程中会持续回调该方法。

 

step

滑块的最小步长,这个值应该在 0 到 (maximumValue - minimumValue) 之间,默认值为 0

 

maximumTrackTintColor

"滑块" 右侧的滑条颜色值。

 

value

"滑块" 的初始值,这个值应该在最小值和最大值(默认 0 - 1)之间,默认值是 0

注意:这不是一个受约束的组件,也就是说,在用户操作后即使你不更新该属性的值,对应组件也不会还原到初始值。

 

thumbTintColor

"滑块" 的前景色,仅适用于 Android 平台。

 

maximumTrackImage

可指定一张静态图片来作为 "滑块" 右侧轨道的背景图,图片最中央的像素会被平铺直至填满轨道,仅适用于 iOS 平台。

 

minimumTrackImage

同 maximumTrackImage,只不过指定的静态图片来作用于右侧轨道。

 

thumbImage

可指定一张静态图片来为 "滑块" 本身设置一张静态图片,仅适用于 iOS 平台。

 

trackImage

为整个轨道设置一张静态背景图,图片最中央的像素会被平铺直至填满轨道,仅适用于 iOS 平台。

常用方法

哈,这个真没有。

小结

这篇文章主要是介绍 Slider 组件的基本使用。

注:在看属性介绍时,结合示例效果图味道更佳噢。

 

 

Switch

一个跨平台的、可以在两个状态 (TRUE or FALSE) 中进行切换的组件。

注意,Switch 是受控组件(controlled component),也就是说:

  • 你必须在 onValueChange 回调中手动更新 value 属性以响应用户的操作。
  • 如果不更新 value 属性,组件只会按一开始给定的 value 值来渲染且保持不变,看上去就像完全点不动。

示例

示例代码:

 

示例效果图 (两个平台都有,而且是动态的噢):

  
 

 


常用属性

disabled

设置 true 时用户不可以改变其开关状态,默认为 false

 

onTintColor

处于 "开" 状态时组件的背景色。

 

onValueChange

当开关状态发生变化时,将会回调的方法。

 

thumbTintColor

"滑块" 的颜色。

If this is set on iOS, the switch grip will lose its drop shadow.

 

tintColor

边框的颜色:

  • iOS 平台:指的是组件的边缘颜色。
  • Android 平台:指的是组件处于「关」状态时的背景色。

 

value

组件的开关状态值,如果为 true 组件将会显示为 "开" 状态样式,默认为 false

常用方法

呃.. 这个是真没有。

小结

这篇文章主要是简单介绍了 React Native 中 Switch 组件的使用,该组件个别属性在不同平台上的显示差异比较大,

一个比较好的做法是抽象出共同的、必须要用到的属性并包装成一个新的组件。

 

Text

Text 是一个用来显示文本的组件,并支持嵌套、样式和触摸事件处理。

示例

在下面的示例中,演示了一个嵌套的 title 和 body 文本组件,并且继承了来自 styles.baseText 的 fontFamily 字体样式,

但其中 title 文本组件使用了额外的 styles.titleText 样式。

 

示例代码:

 

示例效果图:

 

注:在 Android 平台下需要在 /assets/fonts 目录下放一个同名字体文件,即 open-sans-regular.ttf

要注意下 onPress 的写法,以下两种方式是错误的:

 

 

嵌套文本

iOS 和 Android 都允许你通过 "标识一段字符串" 来使其显示特定的样式,比如加粗或显示特定颜色等(类似 iOS 中的 NSAttributedString 和 Android 中的 SpannableString)。

在 React Native 来说,可以通过嵌套 Text 来实现该效果。

示例代码:

 

示例效果图:

本质上,React Native 是通过将上述代码转换为包含以下信息的 NSAttributedString 或 SpannableString 来实现的:

 

 

嵌套 View

在 iOS 平台中,你可以在 Text 组件中嵌套 View 比如:

 


但是,这在 Android 中是会直接报错的,如下图:

布局容器

Text 元素相对布局而言是特殊的,其内部的一切都不再使用 flexbox 布局。

这意味着 Text 的内部元素不再是长方形的了,超过末尾时可以进行换行。

示例代码:

 

示例效果图:

 

限制的样式继承

在 Web 开发中,为整个 document 设置字体和大小的常用方法是利用继承的 CSS 属性,如下所示:

 

然后,这个 document 中的所有元素都会继承该样式除非它们的父元素指定了新的样式规则。

而在 React Native 中,文本的显示与样式相对 Web 来说是更加严格的:

  • 你必须将所有的文本内容放在 <Text> 组件内部,不能直接放在 <View> 组件内部。
 

此外,你还失去了为整个子树设置默认字体的能力。同时,与 CSS 中的 font-family 不同的是,fontFamily 只接受一个字体名称。

要在应用程序中使用一致的字体和大小,推荐的方法是创建一个包含这些字体和大小的组件 MyAppText,并在应用程序中使用这个组件来显示文本。

当然,你也可以基于 MyAppText 组件来为其它类型文本创建更具体的组件,比如 MyAppHeaderText

 

假设 MyAppText 是一个组件,一个只是将其子组件呈现为带有样式的文本组件,那么可以将 MyAppHeaderText 定义如下:

 

以这种方式来组合 MyAppText 可以确保我们从顶级组件获得样式,同时也允许我们在特定的场景中 "添加" 或 "覆盖" 它们。

React Native 仍然有样式继承的概念,但仅限于文本子树。比如下面示例中的第二部分文字将会同时应用到粗体和红色。

 

官方相信,这种更受约束的文本样式将产生更好的应用程序:

  • React 组件在设计时考虑到了强大的隔离性:
    • 你应该能够在应用程序的任何地方删除组件;
    • 只要相信这些属性是相同的,它的外观和行为就会是相同的;
    • 可以从外部继承的文本属性将打破这种隔离。
  • React Native 的实现得到了简化:
    • 我们不需要在每个元素上都有一个 fontFamily 字段;
    • 也不需要每次显示文本节点时都遍历树直到根。
    • 样式继承仅在本机 Native 组件内部编码,不会泄漏到其它组件或系统本身。

常用属性

selectable

决定用户是否可以长按选择文本,以便进行复制和粘贴。

 

ellipsizeMode

省略模式,当设置了 numberOfLines 时,可结合该参数定义了文字会如何被如何截短。其可能值有:

  • 'head':该行末尾适应,开头的缺失文本由省略号表示,比如 "...wxyz"。
  • 'middle':该行头尾适应,中部缺失文本由省略号表示,比如 "ab...yz"。
  • 'tail':该行头部适应,末尾的缺失文本由省略号表示,比如 "abcd..."。
  • 'clip':Lines are not drawn past the edge of the text container, only work on iOS.

默认值为 tail

 

nativeID

Used to locate this view from native code.

 

numberOfLines

用于限制文本行数,通常会与 ellipsizeMode 一起使用,在计算文本布局后通过省略号截短文本 (包括折叠产生的换行在内),总的行数不会超过这个属性的控制。

 

onLayout

类型为函数,在挂载或布局发生变化时会被调用,参数为:{nativeEvent: {layout: {x, y, width, height}}}

 

onLongPress

当文本被长按时会回调的函数,比如:onLongPress={this.increaseSize}>

 

onPress

当文本被点击时会回调的函数,比如:onPress={() => console.log('1st')}

 

pressRetentionOffset

官方文档:When the scroll view is disabled, this defines how far your touch may move off of the button, before deactivating the button. Once deactivated, try moving it back and you'll see that the button is once again reactivated! Move it back and forth several times while the scroll view is disabled. Ensure you pass in a constant to reduce memory allocations.

类型: object: {top: number, left: number, bottom: number, right: number}

 

allowFontScaling

指定字体是否需要随着给定样式的限制而自动缩放,默认为 true

注:可通过该属性来实现 "RN 页面文字不随系统字体大小变化而变化" 的效果,另外,TextInput 也有这个属性噢。

 

style

与常见的 ViewStyle 不同,Text 的 style 类型为 TextStyle,挑些特别的讲下:

  • fontWeight: 字重,可选值有 'normal', 'bold', '100', '200', ... '900'。
  • lineHeight: 行高。
  • textAlign: 文本对齐方式,可选值有 'auto', 'left', 'right', 'center', 'justify'。注意,其中 'justify' 仅支持 iOS,Android 上会变成 'left'
  • fontFamily: 用于指定字体,中文字体文件体积太大了,不建议使用。
  • includeFontPadding: Android 在默认情况下会为文字额外保留一些 padding,以便留出空间摆放上标或是下标的文字。对于某些字体来说,这些额外的 padding 可能会导致文字难以垂直居中。如果你把 textAlignVertical 设置为 'center' 之后,文字看起来依然不在正中间,那么可以尝试将本属性设置为 false
  • ...

有意思的是:在实际使用中发现 textAlign 和 textAlignVertical 在 iOS 并不生效,需要包一层 View 来解决对齐问题。

 

selectionColor

用于指定选中文本的高亮色.

 

textBreakStrategy

enum('simple', 'highQuality', 'balanced')

Set text break strategy on Android API Level 23+, possible values are simple, highQuality, balanced The default value is highQuality.

 

adjustsFontSizeToFit

指定字体是否随着给定样式的限制而自动缩放,仅适用于 iOS 平台。

 

minimumFontScale

当 adjustsFontSizeToFit 启用时,指定字体的最小缩放比(0.01 - 1.00),仅适用于 iOS 平台。

 

suppressHighlighting

如果将其设置为 true 值,那么文本被按下时没有任何视觉效果。默认情况下,文本被按下时会有一个灰色的、椭圆形的高光。

常用方法

这个没有,这个真没有。

小结

这篇文章主要是介绍 Text 组件的基本使用,有个已知问题时:嵌入式 Text 组件不支持 numberOfLines 属性,详情可见 react-native#22811

 

 

Alert

用于显示一个带有指定标题和内容的提示对话框。

支持指定一系列的按钮,点击任何按钮都会回调对应的 onPress 方法并关闭对话框。默认情况下,显示的提示对话框只带有一个 OK / 确定 按钮。

该 API 在 iOS 和 Android 上都可以使用,但如果你想显示一个对话框并让用户输入一些信息,那你可能需要使用 AlertIOS

示例

直接看两个平台上的显示效果先:

  
 

 


iOS

在 iOS 平台上,你可以指定任意数量的按钮。每个按钮可以指定自己样式,比如 'default'、'cancel' 和 'destructive' 其中一个.

Android

在 Android 平台上,最多可以指定三个按钮,这三个按钮可分别理解为三种状态:

  • 中间态 neutral
  • 消极态 negative
  • 积极态 positive

在写代码时,如果你:

  • 只指定一个按钮,那么它具有 "积极态" 的属性,比如 "确定"。
  • 指定了两个按钮,则分别是 "消极态" 和 "积极态",比如 "取消" 和 "确定"。
  • 指定了三个按钮,则分别是 "中间态"、"消极态" 和 "积极态",比如 "稍后再说"、"取消" 和 "确定"。

另外,在 Android 平台上默认点击提示框的外面会自动取消提示框。如果你想阻止这个行为,可以提供一个额外参数 { onDismiss: () => {} }

或者,也可以设置另外一个属性 { cancelable: false } 来阻止。

示例代码片段:

 


相关方法

呃,只有 alert() 这个,其原型如下:

 


小结

一般来说,我们都是将 React Native 作为原生项目的一部分进行使用的,而以前原生部分已经封装好弹窗相关的逻辑并且已有预先定义样式了。

所以,我们一般不会使用 Alert.alert() 来做弹窗逻辑,而是封装一个 Native Module 来实现。

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值