跳至主内容
版本:0.77

图片资源

非官方测试版翻译

本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →

静态图片资源

React Native 提供了统一的方式来管理 Android 和 iOS 应用中的图片及其他媒体资源。要将静态图片添加到应用中,请将其放置在源代码目录树中的任意位置,并按如下方式引用:

tsx
<Image source={require('./my-icon.png')} />

图片名称的解析方式与 JS 模块相同。在上面的示例中,打包器会在引用该图片的组件所在目录中查找 my-icon.png

您可以使用 @2x@3x 后缀为不同屏幕密度提供图片。假设有以下文件结构:

.
├── button.js
└── img
├── check.png
├── check@2x.png
└── check@3x.png

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

tsx
<Image source={require('./img/check.png')} />

...打包器会根据设备屏幕密度自动选择对应图片。例如,iPhone 7 会使用 check@2x.png,而 iPhone 7 Plus 或 Nexus 5 会使用 check@3x.png。如果没有完全匹配的图片,将选择最接近的可用选项。

在 Windows 系统中添加新图片后,可能需要重启打包器。

这种机制具有以下优势:

  1. Android 和 iOS 使用相同机制

  2. 图片与 JavaScript 代码位于相同目录,组件具有自包含性

  3. 无全局命名空间冲突问题

  4. 只有实际使用的图片才会被打包进应用

  5. 增删改图片无需重新编译应用,可通过常规方式刷新模拟器

  6. 打包器自动获取图片尺寸,无需在代码中重复声明

  7. 可通过 npm 包分发图片资源

注意:此机制要求 require 中的图片名称必须是静态已知的。

tsx
// GOOD
<Image source={require('./my-icon.png')} />;

// BAD
const icon = this.props.active
? 'my-icon-active'
: 'my-icon-inactive';
<Image source={require('./' + icon + '.png')} />;

// GOOD
const icon = this.props.active
? require('./my-icon-active.png')
: require('./my-icon-inactive.png');
<Image source={icon} />;

通过此方式引入的图片源包含尺寸(宽/高)信息。如需动态缩放图片(例如通过 flex 布局),可能需要在 style 属性中手动设置 {width: undefined, height: undefined}

静态非图片资源

上述 require 语法也可用于静态引入音频、视频或文档文件。支持常见文件类型如 .mp3, .wav, .mp4, .mov, .html.pdf。完整列表请参考 打包器默认配置

可通过在 Metro 配置中添加 assetExts 解析器选项来支持其他文件类型。

注意事项:视频必须使用绝对定位而非 flexGrow,因为非图片资源当前不会传递尺寸信息。此限制不适用于直接链接到 Xcode 或 Android 资源文件夹的视频。

混合应用中的资源图片

在开发混合应用(部分界面使用 React Native,部分使用平台原生代码)时,仍可使用已打包到应用中的图片。

对于通过 Xcode 资源目录或 Android drawable 文件夹引入的图片,使用不带扩展名的图片名称:

tsx
<Image
source={{uri: 'app_icon'}}
style={{width: 40, height: 40}}
/>

对于 Android assets 文件夹中的图片,使用 asset:/ 协议:

tsx
<Image
source={{uri: 'asset:/app_icon.png'}}
style={{width: 40, height: 40}}
/>

这些方法不提供安全检查,您需要自行确保图片在应用中可用,并需手动指定图片尺寸。

网络图片

应用中显示的许多图片在编译时并不可用,或者您需要动态加载图片以减小二进制体积。与静态资源不同,您需要手动指定图片尺寸。强烈建议使用 https 以满足 iOS 的 应用传输安全 要求。

tsx
// GOOD
<Image source={{uri: 'https://reactjs.org/logo-og.png'}}
style={{width: 400, height: 400}} />

// BAD
<Image source={{uri: 'https://reactjs.org/logo-og.png'}} />

图片的网络请求

如果想为图片请求设置 HTTP 方法、请求头或请求体,可以在源对象中定义这些属性:

tsx
<Image
source={{
uri: 'https://reactjs.org/logo-og.png',
method: 'POST',
headers: {
Pragma: 'no-cache',
},
body: 'Your Body goes here',
}}
style={{width: 400, height: 400}}
/>

数据 URI 图片

有时您可能通过 REST API 调用获取编码的图片数据。可以使用 'data:' URI 方案加载这些图片。与网络资源相同,您需要手动指定图片尺寸

信息

建议仅用于非常小且动态变化的图片,例如数据库返回的列表图标。

tsx
// include at least width and height!
<Image
style={{
width: 51,
height: 51,
resizeMode: 'contain',
}}
source={{
uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg==',
}}
/>

缓存控制

某些场景下,您可能希望仅显示本地缓存中已有的图片(例如先用低分辨率占位图,等高分辨率图加载完成后再替换)。另一些场景中,您不介意显示过期的图片以节省带宽。cache 源属性让您可以控制网络层与缓存的交互方式:

  • default:使用平台默认策略

  • reload:直接从源地址加载数据,不使用任何缓存数据

  • force-cache:优先使用缓存数据(无论是否过期),仅当缓存不存在时才从源地址加载

  • only-if-cached:仅使用缓存数据(无论是否过期),若缓存不存在则直接视为加载失败

tsx
<Image
source={{
uri: 'https://reactjs.org/logo-og.png',
cache: 'only-if-cached',
}}
style={{width: 400, height: 400}}
/>

本地文件系统图片

参考 CameraRoll 了解如何使用 Images.xcassets 之外的本地资源。

选择最佳相册图片

iOS 相册会为同一张图片保存多个尺寸,出于性能考虑选择最接近的尺寸至关重要。在显示 200x200 缩略图时,不应使用全尺寸的 3264x2448 原图。React Native 默认会优先选择精确匹配的尺寸,若不存在则选择比目标尺寸大至少 50% 的最近尺寸,避免缩放导致的模糊问题。所有这些处理都是自动完成的,无需编写繁琐(且易出错)的代码。

为什么不自动适配所有尺寸?

在浏览器中,如果未给图片设置尺寸,浏览器会先渲染 0x0 元素,下载图片后再按正确尺寸渲染。这种行为的最大问题是图片加载时会导致界面跳动,造成糟糕的用户体验(称为累积布局偏移)。

在 React Native 中 我们刻意不实现此行为。虽然开发者需要提前知道远程图片的尺寸(或宽高比)增加了工作量,但我们相信这能带来更好的用户体验。通过 require('./my-icon.png') 语法从应用包加载的静态图片_可以自动获得尺寸_,因为它们的尺寸在挂载时立即可用。

例如,require('./my-icon.png') 可能返回:

tsx
{"__packager_asset":true,"uri":"my-icon.png","width":591,"height":573}

对象形式的图片源

在 React Native 中,一个有趣的设计决策是将 src 属性命名为 source,它不接受字符串参数,而是接收一个包含 uri 属性的对象。

tsx
<Image source={{uri: 'something.jpg'}} />

从底层架构的角度看,这种设计允许我们为这个对象附加元数据。例如当使用 require('./my-icon.png') 时,我们会添加图片的实际位置和尺寸信息(但请不要依赖此特性,未来可能改变)。这种设计也为未来功能留出扩展空间,例如我们可能希望支持精灵图,那么就不再输出 {uri: ...},而是输出 {uri: ..., crop: {left: 10, top: 50, width: 20, height: 40}} 这样的结构,从而在现有调用点透明地支持精灵图功能。

从用户角度看,这让你可以在对象上添加实用属性(如图片尺寸)来计算显示尺寸。你可以将其作为数据结构自由扩展,存储更多图片相关信息。

通过嵌套实现背景图片

熟悉 Web 开发的开发者常要求实现 background-image 功能。为此可以使用 <ImageBackground> 组件,它拥有与 <Image> 相同的 props,你可以在其上叠加任意子组件作为内容层。

由于实现较为基础,某些场景下你可能不想使用 <ImageBackground>。请参考 <ImageBackground>文档获取更多信息,必要时可创建自定义组件。

tsx
return (
<ImageBackground source={...} style={{width: '100%', height: '100%'}}>
<Text>Inside</Text>
</ImageBackground>
);

请注意必须指定宽度和高度样式属性。

iOS 边框圆角样式

请注意 iOS 图片组件可能会忽略以下特定边角的圆角样式属性:

  • borderTopLeftRadius

  • borderTopRightRadius

  • borderBottomLeftRadius

  • borderBottomRightRadius

后台线程解码

图片解码可能超过单帧时间。在 Web 环境中这是导致卡顿的主因之一,因为解码发生在主线程。React Native 在独立线程执行解码。实际上你已需要处理图片未加载完成的状态,因此在解码期间多显示几帧占位图无需代码调整。

配置 iOS 图片缓存限制

在 iOS 平台,我们提供了覆盖 React Native 默认图片缓存限制的 API。请在你的原生 AppDelegate 代码中调用(例如在 didFinishLaunchingWithOptions 方法内)。

objectivec
RCTSetImageCacheLimits(4*1024*1024, 200*1024*1024);

参数:

NameTypeRequiredDescription
imageSizeLimitnumberYesImage cache size limit.
totalCostLimitnumberYesTotal cache cost limit.

上述代码示例中将单张图片大小限制设为 4 MB,总缓存容量限制设为 200 MB。