繁体   English   中英

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

[英]Overlay button on top of Image in React Native

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

角落带有图标的图像

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

我在 React Native 中遇到的问题是 Image 组件的大小并不总是与缩小的图像大小匹配。 如果我将图像的高度固定为 300,设置 flex 1 使图像的宽度扩展以填充其内容,并且图像是肖像,图像组件具有容器的全宽,但组件内的图像将具有宽度要小得多。 因此,让视图覆盖另一个视图的典型方法并不像我希望的那样工作 - 我的覆盖层还覆盖了图像周围的填充,并且按钮(锚定到角落)出现在图像之外。

这是在 React Native 中的样子:

React Native 中带有按钮叠加的肖像图像

X 是按钮的占位符。 它被设置为锚定到视图的左上角,该视图是图像的子视图的子视图。 图片的 backgroundColor 设置为绿色,以演示 Image 组件的宽度与组件内部图片的宽度有何不同。

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

演示代码:

   <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>

从 React-native v0.50.0 开始,不再支持带有嵌套内容的<Image> 请改用<ImageBackground>

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

这是我如何实现的:

import React, { Component } from "react";
import { View, Image, StyleSheet } from "react-native";
import { Ionicons } from "@expo/vector-icons";

class MyCard extends Component {
  render() {
    return (
      <View style={styles.container}>
        <Image
          resizeMode="cover"
          style={styles.cover}
          source={{ uri: "https://picsum.photos/700" }}
        />
        <Ionicons style={styles.close} name="ios-close-circle" size={25} />
      </View>
    );
  }
}

export default MyCard;

const styles = StyleSheet.create({
  container: {
    margin: 5,
    width: 160,
    height: 200
  },
  cover: {
    flex: 1,
    borderRadius: 5
  },
  close: {
    margin: 5,
    position: "absolute",
    top: 0,
    left: 0,
    width: 25,
    height: 25,
    color: "tomato"
  }
});

这是它的样子:

在此处输入图片说明

2019 年 6 月 29 日更新

现在( react-native@0.60-RC )有一个特定的组件可以将元素包装为图像背景ImageBackground 去官方文档。

以下要点已更改。


原答案

我们可以使用<Image/>显示图像,我们可以将其用作background-image黑客。

试试这个

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

这个要点是满足您需求的完整演示。

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

 <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>

所以你这样做的方式,正如@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/轻推你自己/react-native-flexible-thumbnail

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM