首页 文章

React Native中图像顶部的叠加按钮

提问于
浏览
4

我试图在React Native中实现以下效果:

image with an icon in the corner

图像角落有一个按钮 . 无论图像的大小或纵横比如何,按钮始终位于图像的角落内,并且图像的任何部分都不会被剪裁(它总是按比例缩小以完全适合框内) .

我在React Native中遇到的麻烦是Image组件的大小并不总是与图像的缩小尺寸相匹配 . 如果我将图像的高度固定为300,则设置flex 1以使图像的宽度扩展以填充其内容,并且图像为纵向,Image组件具有容器的整个宽度,但组件中的图像将具有宽度要少得多 . 因此,使视图覆盖另一个视图的典型方法不能像我希望的那样工作 - 我的覆盖也覆盖图像周围的填充,并且按钮(锚定到角落)出现在图像外部 .

这是它在React Native中的样子:

portrait image with button overlay in React Native

X是按钮的占位符 . 它被设置为锚定到视图的左上角,该视图是图像所属的相同视图的子视图 . 图像的backgroundColor设置为绿色,以演示Image组件的宽度与组件内部图片的宽度之间的差异 .

目标是无论其纵横比如何,X都将位于图像内部 . 我想我可以做一些基于抓取图像的尺寸和缩放图像组件的高度和宽度,但这听起来复杂和脆弱 . 这是否可以通过样式以响应方式实现?

演示代码:

<View style={{ marginLeft: 7, marginRight: 7, backgroundColor: 'blue', }} > <View style={{ height: 300, flex: 1, }} > <Image source={imageSource} style={{ flex: 1, height: undefined, width: undefined, backgroundColor: 'green', }} resizeMode="contain" /> </View> <View style={{ position: 'absolute', right: 5, top: 5, backgroundColor: 'transparent', }} > <Text style={{ color: 'white' }}>X</Text> </View> </View>

3 回答

  • 0

    来自React-native v0.50.0 <Image> ,不再支持嵌套内容 . 请改用 <ImageBackground> .

    <ImageBackground
      source={imageSource}
    >
        <View>
            <Text>×</Text>
        </View>
    </ImageBackground>
    
  • 1

    我们可以使用 <Image/> 显示图像,我们可以将它用作 background-image hack .

    试试这个

    <Image
      source={imageSource}
    >
      <View>
        <Text>×</Text>
      </View>
    </Image>
    

    this gist 是您需要的完整演示 .

    或者你可以在世博会上看到它:

    <div data-snack-id="B1SsJ7m2b" data-snack-platform="ios" data-snack-preview="true" data-snack-theme="light" style="overflow:hidden;background:#fafafa;border:1px solid rgba(0,0,0,.16);border-radius:4px;height:505px;width:100%"></div>
    <script async src="https://snack.expo.io/embed.js"></script>
    
  • 9

    因此,正如@ObooChin所提到的,这样做的方法是使用Image.getSize()来获取图像的实际大小,然后根据a)想要图像占用的最大空间生成高度和宽度, b)实际图像尺寸的纵横比 .

    import React, { Component } from 'react';
    import {
      StyleSheet,
      Image,
      View,
      Dimensions,
    } from 'react-native';
    
    export default class FlexibleThumbnail extends Component {
    
        constructor(props) {
            super(props)
    
            this.state = {
                imageWidth: 0,
                imageHeight: 0,
                source: null,
            }
        }
    
        componentWillMount() {
            this._updateState(this.props)
        }
    
        componentWillReceiveProps(nextProps) {
            this._updateState(nextProps)
        }
    
        _updateState(props) {
            const {source} = props;
            const height = props.maxHeight;
            const width = props.maxWidth || Dimensions.get('window').width;
    
            const imageUri = source.uri;
    
            Image.getSize(imageUri, (iw, ih) => {
                const {imageWidth, imageHeight} = /* some function that takes max height, width and image height, width and outputs actual dimensions image should be */
    
                this.setState({
                    imageWidth,
                    imageHeight,
                    source,
                });
            });
        }
    
        render() {
            const {source, height, width, imageWidth, imageHeight} = this.state;
    
            const overlay = (/* JSX for your overlay here */);
    
            // only display once the source is set in response to getSize() finishing
            if (source) {
                return (
                    <View style={{width: imageWidth, height: imageHeight}} >
                        <Image
                            style={[ imageStyle, {width: imageWidth, height: imageHeight} ]}
                            resizeMode="contain"
                            source={source}
                        />
                            <View style={{
                                position: 'absolute',
                                top: 0,
                                bottom: 0,
                                left: 0,
                                right: 0,
                                backgroundColor: 'transparent',
                            }}>
                                {overlay}
                            </View>
                    </View>
                );
            }
    
            return (
                <View />
            )
        }
    }
    

    尝试仍然有点粗糙,但我正在努力将其转换为一个库,您可以在其中指定最大高度,宽度和要使用的叠加层,并处理其余的:https://github.com/nudgeyourself/react-native-flexible-thumbnail .

相关问题