Image 组件
常用属性和方法
interface ImageProps {
// 源
source: ImageSourcePropType;
defaultSource?: ImageSourcePropType;
// 样式
style?: StyleProp<ImageStyle>;
resizeMode?: 'cover' | 'contain' | 'stretch' | 'center' | 'repeat';
blurRadius?: number;
// 加载回调
onLoadStart?: () => void;
onLoadEnd?: () => void;
onLoad?: (event: any) => void;
onError?: (event: any) => void;
onProgress?: (event: any) => void;
// 其他
fadeDuration?: number; // Android only
progressiveRenderingEnabled?: boolean; // iOS only
loadingIndicatorSource?: ImageSourcePropType;
}
// 静态方法
interface ImageStatic {
// 预加载
prefetch: (url: string) => Promise<boolean>;
// 查询缓存
queryCache: (urls: string[]) => Promise<{ [key: string]: string }>;
// 获取图片尺寸
getSize: (
uri: string,
success: (width: number, height: number) => void,
failure?: (error: any) => void
) => void;
}
本地图片、网络图片、默认图片
import React from 'react';
import {Image, View, StyleSheet} from 'react-native';
import {Image1, Image2} from '../constants/images';
import LocalImage from './../assets/images/1.jpeg';
export default () => {
return (
<View style={styles.container}>
{/* 本地图片 */}
<Image source={LocalImage} style={styles.image} />
{/* 网络图片 */}
<Image
source={{
uri: `${Image1}`,
}}
style={styles.image}
/>
{/* 带默认图的网络图片 */}
<Image
defaultSource={LocalImage}
source={{uri: `${Image2}`}}
style={styles.image}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
image: {
width: 200,
height: 200,
marginVertical: 10,
},
});

调整大小和缩放模式
cover 模式
export default () => {
return (
<View>
{/* cover 模式 */}
<View style={styles.wrapper}>
<Image source={LocalImage1} style={styles.image} resizeMode="cover" />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
wrapper: {
width: '100%',
height: '100%',
backgroundColor: '#C9CEC9',
},
image: {
width: 200,
height: 200,
},
});

contain 模式
export default () => {
return (
<View>
{/* contain 模式 */}
<View style={styles.wrapper}>
<Image source={LocalImage1} style={styles.image} resizeMode="contain" />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
wrapper: {
width: '100%',
height: '100%',
backgroundColor: '#C9CEC9',
},
image: {
width: 200,
height: 200,
},
});

stretch 模式
export default () => {
return (
<View>
{/* stretch模式 */}
<View style={styles.wrapper}>
<Image source={LocalImage1} style={styles.image} resizeMode="stretch" />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
wrapper: {
width: '100%',
height: '100%',
backgroundColor: '#C9CEC9',
},
image: {
width: 200,
height: 200,
},
});

center 模式
export default () => {
return (
<View>
{/* center 模式 */}
<View style={styles.wrapper}>
<Image source={LocalImage1} style={styles.image} resizeMode="center" />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
wrapper: {
width: '100%',
height: '100%',
backgroundColor: '#C9CEC9',
},
image: {
width: 200,
height: 200,
backgroundColor: '#fff',
},
});

repeat 模式
export default () => {
return (
<View>
{/* repeat模式 */}
<View style={styles.wrapper}>
<Image source={LocalImage1} style={styles.image} resizeMode="repeat" />
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
},
wrapper: {
width: '100%',
height: '100%',
backgroundColor: '#C9CEC9',
},
image: {
width: 200,
height: 200,
backgroundColor: '#fff',
},
});

blurRadius
用于给图片添加高斯模糊效果。值越高越模糊
blurRadius 的基本限制:
- 最小值:0(无模糊)
- 最大值:没有严格限制,但建议不超过 25
- 只接受数值类型
<Image
source={LocalImage1}
style={styles.image}
resizeMode="center"
blurRadius={8}
/>

fadeDuration
渐入动画时间,用于控制图片淡入动画的持续时间(以毫秒为单位)。这个属性仅在 Android 平台上可用。
fadeDuration 的基本限制:
- 最小值:0(立即显示,无淡入效果)
- 默认值:300
- 最大值:理论上没有严格限制,但建议不超过 1000-1500ms
推荐使用范围:
const FadeDuration = {
NONE: 0, // 无淡入效果
FAST: 200, // 快速淡入
DEFAULT: 300, // 默认淡入时间
MEDIUM: 500, // 中等淡入时间
SLOW: 750, // 慢速淡入
MAX: 1000 // 建议最大值
};
实际使用建议:
- 列表/网格:200-300ms
- 预览图:300-500ms
- 背景切换:500-1000ms
加载回调
- onLoadStart: 开始加载图片时触发
- onLoad:加载成功触发
- onError:加载失败触发
- onLoadEnd: 图片加载完成或失败时触发(无论成功还是失败都会触发)
onLoad
import LocalImage1 from '../assets/images/1.jpeg';
...
...
<View style={styles.wrapper}>
<Image
source={LocalImage1}
onLoad={event => {
console.log(event.nativeEvent);
}}
/>
</View>
...
// onLoad
// event.nativeEvent
{"source": {"height": 525, "uri": "http://10.0.2.2:8081/assets/src/assets/images/1.jpeg?platform=android&hash=c93e2c55e5d5cfaae84dd939b3eed8d5", "width": 525}}
onError
什么时候才会触发 onError?
要触发 onError,需要提供一个格式正确但无法访问或不存在的图片 URL
// 使用一个不存在的完整 URL
source={{ uri: 'https://example.com/non-existent-image.jpg' }}
// 或者一个错误格式的 URL
// source={{ uri: 'https://broken-url' }}
- URI 需要是有效的 URL 格式
- 比如单个字符 'a' 不是有效的 URL
- React Native 可能在验证 URL 格式时就拦截了这种明显无效的 URI
- 不触发 onError
<View style={styles.wrapper}>
<Image
source={{uri: 'example.jpg'}}
onLoad={event => {
console.log(event.nativeEvent);
}}
onError={event => {
console.log(event.nativeEvent);
}}
/>
</View>
// 触发的是onLoad
{"source": {"height": 525, "uri": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=", "width": 525}}
- 触发 onError
<View style={styles.wrapper}>
<Image
source={{uri: 'https://example.com/non-existent-image.jpg'}}
onLoad={event => {
console.log(event.nativeEvent);
}}
onError={event => {
console.log(event.nativeEvent);
}}
/>
</View>
// onError
{"error": "Unexpected HTTP code Response{protocol=h2, code=404, message=, url=https://example.com/non-existent-image.jpg}"}
onLoadStart
没有event.nativeEvent
onLoadEnd
没有event.nativeEvent
tintColor
用于给图片添加着色效果。它主要用于改变图片的颜色,特别适用于图标和单色图片。
- tintColor 主要用于改变图片颜色
- 最适合用于单色图标和 PNG 透明图片
- 可以使用任何有效的颜色值(名称、十六进制、rgba)
- 常用于主题切换和状态指示
const IconExample = ({ active }) => {
return (
<Image
source={require('./assets/tab-icon.png')}
style={styles.icon}
tintColor={active ? '#007AFF' : '#8E8E93'}
/>
);
};
// tintColor 最好用于带透明度的 PNG 图片
const TransparentIcon = () => {
return (
<Image
source={require('./transparent-icon.png')} // PNG with transparency
tintColor="#007AFF"
/>
);
};
Image API
- getSize,用于在加载图片前获取图片的尺寸,不能用于本地图片
import {Image1} from '../constants/images';
...
...
useEffect(() => {
Image.getSize(
Image1,
(width, height) => {
console.log('success load Image1: ', width, height);
},
error => {
console.log(error);
},
);
}, []);
...
- prefetch,用于预加载图片。返回一个 Promise
Image.prefetch(Image1)
.then(data => {
console.log('prefetch Iamge1 result: ', data);
})
.catch(e => {
console.log(e);
});
- queryCache,用于查询图片的缓存状态。它接收一个 URL 数组,返回一个 Promise,解析为一个对象,包含每个 URL 的缓存状态。
const cached = await Image.queryCache(urls);
console.log('缓存状态:', cached);
// cached 可能的结果:
// {
// 'https://example.com/image1.jpg': 'memory', // 在内存中
// 'https://example.com/image2.jpg': 'disk', // 在磁盘中
// 'https://example.com/image3.jpg': 'undefined' // 图片未缓存
// }
例子,只预加载未缓存的图片:
const SmartPreloader = ({ imageUrls }) => {
const preloadImages = async () => {
try {
// 检查哪些图片已经缓存
const cacheStatus = await Image.queryCache(imageUrls);
// 只预加载未缓存的图片
const needsPreload = Object.entries(cacheStatus)
.filter(([_, status]) => !status)
.map(([url]) => url);
if (needsPreload.length > 0) {
console.log(`预加载 ${needsPreload.length} 张图片`);
await Promise.all(
needsPreload.map(url => Image.prefetch(url))
);
}
} catch (error) {
console.error('预加载失败:', error);
}
};
useEffect(() => {
preloadImages();
}, [imageUrls]);
return null;
};
ImageBackground
ImageBackground 是 React Native 中用于创建带背景图片的容器组件。它实际上是 Image 和 View 的组合。
例子:
import React from 'react';
import {ImageBackground, Text, StyleSheet} from 'react-native';
import LocalImage3 from '../assets/images/3.jpeg';
export default () => {
return (
<ImageBackground
source={LocalImage3}
style={styles.background}
resizeMode="cover">
<Text style={styles.text}>Hello World</Text>
</ImageBackground>
);
};
const styles = StyleSheet.create({
background: {
width: '100%',
height: '100%',
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'red',
},
text: {
color: 'white',
fontSize: 24,
fontWeight: 'bold',
},
});

常见属性
const ImageBackgroundProps = () => {
return (
<ImageBackground
// 图片源
source={require('./background.jpg')}
// 样式
style={styles.background}
// 图片样式
imageStyle={styles.image}
// 调整大小模式
resizeMode="cover"
// 模糊效果
blurRadius={5}
// 加载指示器
loadingIndicatorSource={require('./loading.gif')}
// 图片加载事件
onLoadStart={() => console.log('开始加载')}
onLoad={() => console.log('加载完成')}
onError={() => console.log('加载失败')}
>
{/* 子组件 */}
</ImageBackground>
);
};
imageStyle 和 style 属性的区别
-
style: 应用于容器组件(外层View)的样式
-
imageStyle: 应用于背景图片(Image)的样式
import React from 'react';
import { ImageBackground, Text, StyleSheet } from 'react-native';
const StyleDifferenceExample = () => {
return (
<ImageBackground
source={require('./background.jpg')}
// style 控制整个容器
style={{
width: 300,
height: 200,
justifyContent: 'center',
alignItems: 'center',
borderWidth: 2,
borderColor: 'black',
margin: 10,
}}
// imageStyle 只控制背景图片
imageStyle={{
borderRadius: 20,
opacity: 0.7,
tintColor: 'gray',
}}
>
<Text>Hello World</Text>
</ImageBackground>
);
};
Image 和 ImageBackground 的区别
-
基本定义:
- Image 用于显示图片的基础组件
- ImageBackground 可以包含其他组件的图片容器
-
组件结构和样式:
- Image 单一组件,单一 style 属性
- ImageBackground 实际上是 Image + View 的组合,style 和 imageStyle 两个样式属性
-
性能考虑:
- Image: 较轻量
- ImageBackground: 较重,需要额外的 View 包装
-
应用场景:
- Image: 图片、图标、头像等
- ImageBackground: 登录页面、卡片背景等
-
功能上:
- Image: 主要用于图片显示
- ImageBackground: 可以添加遮罩、渐变等效果