前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >React native 之Image 图片封装为iOS UIImageView contentMode 填充

React native 之Image 图片封装为iOS UIImageView contentMode 填充

作者头像
onety码生
发布2018-11-21 10:20:02
1.5K0
发布2018-11-21 10:20:02
举报
文章被收录于专栏:码生

在使用 Image 组件的时候,受到Image 组件的困扰: 图片的宽度在指定宽度的情况下是可以控制图片的宽度的,但是

  1. 如果我们想要图片的宽度与父视图的宽度一致
  2. 我们想要类似于 iOS 中 UIView->contentMode 的填充方式

针对第一种情况,我将图片 resizeMode 设置为 'stretch' 并且采用 absolute 然后设置 left right 这种方式,但是发现图片的宽度采用这种方式居然限制不了,图片有多大便显示多大,可能比父组件小,也可能超出父组件(没有设置 overflow: hidden 的情况下),所以对图片的宽度等于父视图宽度无法控制(哪位朋友有直接控制的方法请留言告知一下,谢谢)。

我不希望有那个控件不在自己控制之下,于是作为iOS(OC/Swift)的一名开发人员,便想起了封装一个iOS中图片填充方式的图片组件,图片的填充类型为:

代码语言:javascript
复制
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,

代码语言:javascript
复制
'cover', 'contain', 'stretch', 'repeat', 'center'

期望:在使用 scaleToFill 的时候,能解决上面 1 的问题。其他的填充类型也是按照iOS中的填充类型设置

iOS中 UIView -> contentMode 绝对可以满足你的各种图片填充类型,所以此图片封装组件也可以满足你各种图片布局

以下是实现方案: 将图片放置一个 View 上面,在 View onLayout 回调中,知道此 View 的width height,然后在需要将图片的宽度设置为父视图的宽度时候,直接设置图片的宽度为 width。其他 mode 根据 justfiycontent 和 alignItems 等配合使用

代码语言:javascript
复制
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',
    }
});
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.07.09 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档