设计

Style

所有的 core components 都接受一个名为 style 的 prop 。stylenamevalue 与 web 上使用的 CSS 类似,不同的是 name 使用了驼峰命名法,比如 backgroundColor ,而不是 CSS 上的 background-color

style prop 可以是一个 plain old JavaScript object ,这是我们的示例代码中经常使用的。你也可以传递一个 style 数组,数组中的最后一个样式具有优先权 (precedence) ,因此可以使用它来继承样式。

当组件的样式变得复杂时,通常会使用 StyleSheet.create 在一个地方定义所有的 style

示例:

import React from 'react';
import { StyleSheet, Text, View } from 'react-native';

const LotsOfStyles = () => {
    return (
      <View style={styles.container}>
        <Text style={styles.red}>just red</Text>
        <Text style={styles.bigBlue}>just bigBlue</Text>
        <Text style={[styles.bigBlue, styles.red]}>bigBlue, then red</Text>
        <Text style={[styles.red, styles.bigBlue]}>red, then bigBlue</Text>
      </View>
    );
};

const styles = StyleSheet.create({
  container: {
    marginTop: 50,
  },
  bigBlue: {
    color: 'blue',
    fontWeight: 'bold',
    fontSize: 30,
  },
  red: {
    color: 'red',
  },
});

export default LotsOfStyles;

一种常见的模式是让你的组件接受一个 style prop ,然后此 style 会作用于这个组件的子组件。通过这种方式来实现类似 CSS 中的样式级联 (cascade)

Height and Width

Fixed Dimensions

设置组件尺寸的的一般方式是在 style 中添加固定的 widthheightReact Native 中的所有维度都是无单位的,表示与密度无关的像素。

示例:

Flex Dimensions

在组件的 style 中使用 flex 以根据可用空间的大小来动态地展开和收缩组件。通常你会使用 flex: 1 ,它告诉组件填满所有可用空间,并在具有相同父组件的其他组件之间平均共享。给定的 flex 值越大,组件所占的空间比就越高。

A component can only expand to fill available space if its parent has dimensions greater than 0. If a parent does not have either a fixed width and height or flex, the parent will have dimensions of 0 and the flex children will not be visible.

在这个例子中,如果把父组件的 style={{ flex: 1 } 去掉,由于父组件没有了任何 dimension ,因此所有的子组件就都无法展开了;如果把父组件的 flex: 1 改成 height: 300 ,能正常显示,父组件的高度变成了 300px ,子组件也相应缩小了。

Percentage Dimensions

文档中说:

Similar to flex dimensions, percentage dimensions require parent with a defined size.

但我把父组件的 style={{ height: '100%' }} 去掉后,子组件还是能正常展示,为什么呢?

Layout with Flexbox

Flexbox works the same way in React Native as it does in CSS on the web, with a few exceptions. The defaults are different, with flexDirection defaulting to column instead of row, alignContent defaulting to flex-start instead of stretch, flexShrink defaulting to 0 instead of 1, the flex parameter only supporting a single number.

一个组件可以使用 Flexbox algorithm 来指定它的子组件的布局。Flexbox 的设计宗旨是在不同的屏幕尺寸上提供一致的布局。常用的有 flexDirection, alignItems, justifyContent

Flex

flexarrow-up-right 定义了组件的填充方式。

示例:

Flex Direction

flexDirectionarrow-up-right 用于控制子组件的布局方向。

  • column(默认值)

  • row

  • column-reverse

  • row-reverse

示例:

Layout Direction

Layout directionarrow-up-right 指定层次结构中的子元素和文本的布局方向。

  • LTR(默认值):从左向右布局。

  • RtL:从右向左布局。

示例:

Justify Content

justifyContentarrow-up-right 描述了如何在其容器的主轴内对齐子容器。

  • flex-start:默认值;

  • flex-end

  • center

  • space-between

  • space-around:均匀排列每个元素,每个元素周围分配相同的空间;

  • space-evenly:均匀排列每个元素,每个元素之间的间隔相等。

可参考 MDN 中的 CSS 的文档arrow-up-right

Align Items

alignItemsarrow-up-right 描述了子组件在容器横轴上的排列方式。alignItemsjustifyContent 非常相似,不同的是 justifyContent 应用于主轴 (main axis)alignItems 应用于横轴 (cross axis)

  • stretch:默认值,拉伸容器中的子组件以匹配容器横轴的 height

  • flex-start

  • flex-end

  • center

  • baseline

说明:要使 stretch 生效,子组件不能设置 fixed dimension

Align Self

alignSelfarrow-up-right 控制子组件在横轴上的排列方式,且会覆盖其父组件设置的 alignItems

示例:

Align Content

alignContentarrow-up-right defines the distribution of lines along the cross-axis. This only has effect when items are wrapped to multiple lines using flexWrap.

Flex Wrap

flexWraparrow-up-right 属性设置在容器上,它控制子组件沿主轴溢出时发生的情况。默认情况下,子元素被强制缩为一行(which can shrink elements)。如果允许 wrap ,则需要沿着主轴将物品 wrap 成多条线。

在使用 wrap 时,可以使用 alignContent 指定如何在容器中放置行。

Flex Basis, Grow, and Shrink

flexBasis

flexBasisarrow-up-right 是使用与轴无关 (axis-independent) 的方式为子组件设置沿主轴方向的默认大小。为子组件设置 flexBasis 与以下的操作效果一样:

  • 如果父组件设置了 flexDirection: row ,设置子组件的 flexBasis 相当于为子组件设置了 width

  • 如果父组件设置了 flexDirection: column ,设置子组件的 flexBasis 相当于为子组件设置了 height

flexBasis 设置的大小是子组件的默认大小,是 flexGrowflexShrink 计算完成之前使用的值。

参考:MDN CSS flex-basisarrow-up-right

flexGrow

flexGrowarrow-up-right 设置了一个 flex 项主尺寸的 flex 增长系数。它指定了 flex 容器中剩余空间的多少应该分配给项目( flex 增长系数)。默认值是 0

主尺寸是项的宽度或高度,这取决于 flexDirection 值。

剩余的空间是 flex 容器的大小减去所有 flex 项的大小加起来的大小。如果所有的兄弟项目都有相同的 flexGrow 系数,那么所有的项目将获得相同的剩余空间,否则将根据不同的 flexGrow 系数定义的比例进行分配。

flexGrow 与其他的 flex 属性 flexShrinkflexBasis 一起使用,通常使用 flex 速记来定义,以确保所有的值都被设置。默认值是 0 ( Web 上默认值是 1 )。

参考:MDN CSS flex-growarrow-up-right

flexShrink

flexShrink 属性指定了 flex 元素的收缩规则。flex 元素仅在默认宽度之和大于容器的时候才会发生收缩,其收缩的大小是依据 flexShrink 的值。

参考:MDN CSS flex-shrinkarrow-up-right

flexBasis、flexGrow、flexShrink 示例

这个示例有一些 Bug 待修复。

Width and Height

指定元素的宽高。widthheight 都使用下述的值:

  • auto:默认值,React Native 根据元素的内容来计算它的宽高;

  • pixels:以绝对像素定义宽度/高度。根据组件上设置的其他样式,这可能是节点的最终维度,也可能不是。

  • percentage:分别以其父元素宽度或高度的百分比定义宽度或高度。

示例:

Absolute & Relative Layout

position 定义了元素在父组件中的定位方式。

  • relative:默认值,元素的定位是相对的。

  • absolute:元素的布局是绝对的,它的布局独立于它的兄弟节点。

示例:

Images

Static Image Resources

打入 bundle 中的静态图片在使用时可以不指定宽高,bundler 能获取其默认大小。

React Native 提供了一种统一的方式来管理你的 Android 和 iOS 应用中的图像和其他媒体资源。

图像名称的解析方式与 JS 模块的解析方式相同。在上述例子中,bundler 将在与需要它的组件相同的文件夹中寻找 my-icon.png

你可以使用 @2x@3x 后缀为不同像素密度的屏幕提供图片。如果你有下面这样的文件结构:

且在 button.js 的代码中包含:

check@2x.png 将用于 iPhone 7check@3x.png 将用于 iPhone 7 Plus 。如果没有匹配屏幕密度的图像,将选择最接近的选项。

使用静态图片资源的示例:

Static Non-Image Resources

上面描述的 require 语法也可以用于静态地包含在项目中的音频视频文档文件。支持的最常见的文件类型包括 .mp3.wav.mp4.mov.html.pdf 等。

需要注意的是,视频必须使用绝对定位 (absolute positioning) 而不是 flexGrow ,因为大小信息目前不传递给非图像资产。对于直接链接到 Xcode 或 Android 的 Assets 文件夹中的视频,则不会出现这种限制。

Images From Hybrid App's Resources

如果你在构建一个 hybrid 应用(一些 UI 使用 React Native,另一些 UI 使用 Native 的),你可以在 RN 中使用已经打包到 App 中的图片。

在 Xcode 的 asset 中或 Android 的 drawable 目录中的图片,使用不带拓展名的图片名称:

在 Android assets 目录中的图片,需要使用 asset:/ scheme :

这些方法不提供安全检查。你要确保这些图像在 App 中可用。你还必须手动指定图像尺寸。

Network Images

和静态资源不同的是,你需要手动指定从网络中下载的图片的宽高:

如果你想在图片的请求中添加 header 和 body ,你可以在 source 对象中设置它们。

示例:

这个图片资源是否不能这样请求,貌似加了这些参数后就无法正常显示了,只有最开始闪一下就再也不展示了。

Uri Data Images

有时,你可能会从 REST API 调用获得编码后的图像数据。你可以使用 data: uri scheme 来使用这些图片。和网络资源一样,你需要手动指定图片的宽高。

示例:

Cache Control (iOS Only)

cache 属性使你可以控制网络层如何与 cache 交互。

  • default:使用 Native 代码中设置的策略;

  • reload:(不使用缓存、只从网络加载)URL 的数据将从原始源加载。不应该使用现有的缓存数据来满足 URL 加载请求。

  • force-cache(优先使用缓存,若缓存没有则从网络加载)现有的缓存数据将用于满足请求,而不管它的过期日期。如果缓存中没有与请求对应的现有数据,则从原始源加载数据。

  • only-if-cached:(只从缓存中获取图片,如果缓存没有则加载失败)现有的缓存数据将用于满足请求,而不管它的过期日期。如果缓存中没有与 URL 加载请求对应的数据,则不会尝试从原始源加载数据,然后加载被认为失败。

示例:

Local Filesystem Images

有关使用 Images.xcassets 之外的本地资源的示例,请参阅 react-native-camerarollarrow-up-right

Background Image via Nesting

与 Web 上的 background-image 类似,React Native 使用 <ImageBackground>arrow-up-right 组件展示背景图片,它的 props 和 <Image> 组件一样。

<ImageBackground> 组件有时候可能不能我们的更定制化的需求,如果要自定义背景图组件,请参看 ImageBackground 组件的文档arrow-up-right

示例:

iOS Border Radius Styles

Please note that the following corner specific, border radius style properties are currently ignored by iOS's image component:

  • borderTopLeftRadius

  • borderTopRightRadius

  • borderBottomLeftRadius

  • borderBottomRightRadius

Last updated