在使用 Image 组件的时候,受到Image 组件的困扰: 图片的宽度在指定宽度的情况下是可以控制图片的宽度的,但是
针对第一种情况,我将图片 resizeMode 设置为 'stretch' 并且采用 absolute 然后设置 left right 这种方式,但是发现图片的宽度采用这种方式居然限制不了,图片有多大便显示多大,可能比父组件小,也可能超出父组件(没有设置 overflow: hidden 的情况下),所以对图片的宽度等于父视图宽度无法控制(哪位朋友有直接控制的方法请留言告知一下,谢谢)。
我不希望有那个控件不在自己控制之下,于是作为iOS(OC/Swift)的一名开发人员,便想起了封装一个iOS中图片填充方式的图片组件,图片的填充类型为:
contentMode: React.PropTypes.oneOf([
'default',
'scaleToFill',
'scaleAspectFit',
'scaleAspectFill',
'center',
'top',
'bottom',
'left',
'right',
'topLeft',
'topRight',
'bottomLeft',
'bottomRight'])
contentMode 比iOS中 UIView contentMode 的类型多了一种 default,此类型类似于 topLeft ,并且保留 react-native Image 组件的 resizeMode,
'cover', 'contain', 'stretch', 'repeat', 'center'
期望:在使用 scaleToFill 的时候,能解决上面 1 的问题。其他的填充类型也是按照iOS中的填充类型设置
iOS中 UIView -> contentMode 绝对可以满足你的各种图片填充类型,所以此图片封装组件也可以满足你各种图片布局
以下是实现方案: 将图片放置一个 View 上面,在 View onLayout 回调中,知道此 View 的width height,然后在需要将图片的宽度设置为父视图的宽度时候,直接设置图片的宽度为 width。其他 mode 根据 justfiycontent 和 alignItems 等配合使用
import React, { Component } from 'react';
import {
View,
Image,
StyleSheet,} from 'react-native'
export default class KKImage extends Component {
constructor(props) {
super(props);
this.state = {
style: {},
selfStyle: {},
resizeMode: 'stretch',
}
}
reLayout(event) {
let mode = this.props.contentMode;
if (!mode) {
mode = 'scaleToFill'
}
// 默认情况下
if (mode == 'default' || mode == 'topLeft') {
this.setState({
style: {},
resizeMode: null,
selfStyle: styles.defaultStyle,
});
}
else if (mode == 'stretch') {
this.setState({
style: {},
resizeMode: 'stretch',
selfStyle: styles.defaultStyle,
});
}
else if (mode == 'cover') {
this.setState({
style: {},
resizeMode: 'cover',
selfStyle: styles.defaultStyle,
});
}
else if (mode == 'contain') {
this.setState({
style: {},
resizeMode: 'contain',
selfStyle: styles.defaultStyle,
});
}
else if (mode == 'repeat') {
this.setState({
style: {},
resizeMode: 'repeat',
selfStyle: styles.defaultStyle,
});
}
// 不等例铺满、拉伸铺满
else if (mode == 'scaleToFill') {
this.setState({
style: {
width: event.nativeEvent.layout.width,
height: event.nativeEvent.layout.height,
},
resizeMode: 'stretch',
selfStyle: styles.defaultStyle,
});
}
// 缩放按照比例内置
else if (mode == 'scaleAspectFit') {
this.setState({
style: {
width: event.nativeEvent.layout.width,
height: event.nativeEvent.layout.height,
},
resizeMode: 'contain',
selfStyle: styles.defaultStyle,
});
}
// 缩放按照比例铺满
else if (mode == 'scaleAspectFill') {
this.setState({
style: {
width: event.nativeEvent.layout.width,
height: event.nativeEvent.layout.height,
},
resizeMode: 'cover',
selfStyle: styles.defaultStyle,
});
}
else if (mode == 'center') {
this.setState({
style: {} ,
resizeMode: null,
selfStyle: [styles.defaultStyle, {justifyContent: 'center', alignItems: 'center'}]
});
}
else if (mode == 'top') {
this.setState({
style: {} ,
resizeMode: null,
selfStyle: [styles.defaultStyle, {alignItems: 'center'}]
});
}
else if (mode == 'bottom') {
this.setState({
style: {} ,
resizeMode: null,
selfStyle: [styles.defaultStyle, {justifyContent: 'flex-end', alignItems: 'center'}]
});
}
else if (mode == 'left') {
this.setState({
style: {} ,
resizeMode: null,
selfStyle:[styles.defaultStyle, {justifyContent: 'center'}]
});
}
else if (mode == 'right') {
this.setState({
style: {} ,
resizeMode: null,
selfStyle:[styles.defaultStyle, {justifyContent: 'center', alignItems: 'flex-end'}]
});
}
else if (mode == 'topRight') {
this.setState({
style: {} ,
resizeMode: null,
selfStyle: [styles.defaultStyle, {alignItems: 'flex-end'}],
});
}
else if (mode == 'bottomLeft') {
this.setState({
style: {} ,
resizeMode: null,
selfStyle: [styles.defaultStyle, {justifyContent: 'flex-end'}]
});
} else if (mode == 'bottomRight') {
this.setState({
style: {} ,
resizeMode: null,
selfStyle: [styles.defaultStyle, {justifyContent: 'flex-end', alignItems: 'flex-end'}]
});
}
}
render() {
return (
<View style={[this.props.style, this.state.selfStyle]}
onLayout={(event)=>{
this.reLayout(event)
}}
>
<Image {...this.props} style={this.state.style} resizeMode={this.state.resizeMode}/>
</View>
);
}
}
KKImage.propTypes = {
contentMode: React.PropTypes.oneOf([
'default',
'cover',
'contain',
'stretch',
'repeat',
'scaleToFill',
'scaleAspectFit',
'scaleAspectFill',
'center',
'top',
'bottom',
'left',
'right',
'topLeft',
'topRight',
'bottomLeft',
'bottomRight']),
};
const styles = StyleSheet.create({
defaultStyle: {
overflow: 'hidden',
}
});