图片资源
本页面由 PageTurner AI 翻译(测试版)。未经项目官方认可。 发现错误? 报告问题 →
静态图片资源
React Native 提供了统一的方式来管理 Android 和 iOS 应用中的图片及其他媒体资源。要将静态图片添加到应用中,请将其放置在源代码目录树中的任意位置,并按如下方式引用:
<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 中的代码包含:
<Image source={require('./img/check.png')} />
...打包器会根据设备屏幕密度自动选择对应图片。例如,iPhone 7 会使用 check@2x.png,而 iPhone 7 Plus 或 Nexus 5 会使用 check@3x.png。如果没有完全匹配的图片,将选择最接近的可用选项。
在 Windows 系统中添加新图片后,可能需要重启打包器。
这种机制具有以下优势:
-
Android 和 iOS 使用相同机制
-
图片与 JavaScript 代码位于相同目录,组件具有自包含性
-
无全局命名空间冲突问题
-
只有实际使用的图片才会被打包进应用
-
增删改图片无需重新编译应用,可通过常规方式刷新模拟器
-
打包器自动获取图片尺寸,无需在代码中重复声明
-
可通过 npm 包分发图片资源
注意:此机制要求 require 中的图片名称必须是静态已知的。
// 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 文件夹引入的图片,使用不带扩展名的图片名称:
<Image
source={{uri: 'app_icon'}}
style={{width: 40, height: 40}}
/>
对于 Android assets 文件夹中的图片,使用 asset:/ 协议:
<Image
source={{uri: 'asset:/app_icon.png'}}
style={{width: 40, height: 40}}
/>
这些方法不提供安全检查,您需要自行确保图片在应用中可用,并需手动指定图片尺寸。
网络图片
应用中显示的许多图片在编译时并不可用,或者您需要动态加载图片以减小二进制体积。与静态资源不同,您需要手动指定图片尺寸。强烈建议使用 https 以满足 iOS 的 应用传输安全 要求。
// 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 方法、请求头或请求体,可以在源对象中定义这些属性:
<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 方案加载这些图片。与网络资源相同,您需要手动指定图片尺寸。
建议仅用于非常小且动态变化的图片,例如数据库返回的列表图标。
// 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:仅使用缓存数据(无论是否过期),若缓存不存在则直接视为加载失败
<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') 可能返回:
{"__packager_asset":true,"uri":"my-icon.png","width":591,"height":573}
对象形式的图片源
在 React Native 中,一个有趣的设计决策是将 src 属性命名为 source,它不接受字符串参数,而是接收一个包含 uri 属性的对象。
<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> 的文档获取更多信息,必要时可创建自定义组件。
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 方法内)。
RCTSetImageCacheLimits(4*1024*1024, 200*1024*1024);
参数:
| Name | Type | Required | Description |
|---|---|---|---|
| imageSizeLimit | number | Yes | Image cache size limit. |
| totalCostLimit | number | Yes | Total cache cost limit. |
上述代码示例中将单张图片大小限制设为 4 MB,总缓存容量限制设为 200 MB。