跳至主内容
版本:0.82

图片资源

非官方测试版翻译

本页面由 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 之外的本地资源。

Drawable 资源

Android 支持通过 xml 文件类型加载 drawable 资源。这意味着您可以使用 矢量图 渲染图标或 图形资源 绘制形状!这些资源的引入方式与其他 静态资源混合应用资源 相同,但 必须手动指定尺寸

对于与你的 JS 代码位于同一目录的静态 drawable,请使用 requireimport 语法(两者效果相同):

tsx
<Image
source={require('./img/my_icon.xml')}
style={{width: 40, height: 40}}
/>

Android drawable 文件夹资源res/drawable)请使用不带扩展名的资源名称:

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

关键差异:drawable 资源必须在 Android 应用编译时引用,因为 Android 需要运行 资源打包工具 (AAPT) 处理资源。Metro 无法通过网络加载 AAPT 生成的二进制 XML 格式。修改资源目录或名称后,每次均需重新构建 Android 应用。

创建 XML drawable 资源

Android 在其 Drawable 资源指南中提供了每种支持的可绘制资源类型的全面文档,并附有原始 XML 文件的示例。您可以使用 Android Studio 中的工具(如 Vector Asset Studio)从可缩放矢量图形 (SVG) 和 Adobe Photoshop 文档 (PSD) 文件创建矢量可绘制对象。

信息

若要将 XML 文件视为静态图片资源(即通过 importrequire 语句引用),您应尽量避免在创建的 XML 文件中引用其他资源。如需使用对其他可绘制对象或属性(如颜色状态列表尺寸资源)的引用,应将可绘制对象作为混合资源引入,并按名称导入。

选择最佳相册图片

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。