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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/46576673/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 06:47:15  来源:igfitidea点击:

Overlay button on top of Image in React Native

javascriptimagereact-native

提问by Keith Kurak

I'm trying to achieve the following effect in React Native:

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

image with an icon in the corner

角落带有图标的图像

The image has a button in the corner. The button is always within the corner of the image regardless of the image's size or aspect ratio, and no part of the image is clipped (it is always scaled down to fit fully within a box).

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

The trouble I'm having in React Native is that the Image component's size doesn't always match the scaled-down size of the image. If I fix the image's height to 300, set flex 1 to make the image's width expand to fill its contents, and the image is a portrait, the Image component with being the full width of the container, but the image within the component will have a width of much less. Therefore, the typical approach for having a view overlay another view doesn't work as I would like it to- my overlay also covers the padding around the image, and the button (anchored to the corner) appears outside of the image.

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

Here's what it looks like in React Native:

这是在 React Native 中的样子:

portrait image with button overlay in React Native

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

The X is a placeholder for the button. It is set to anchor to the top-left of a View that's a child of the same View that the Image is a child of. The backgroundColor of the image is set to green to demonstrate how the width of the Image component is different from the width of the picture that's inside the component.

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

The goal is that the X would be inside of the image regardless of its aspect ratio. I think I could do something based on grabbing the image's dimension and scaling the height and width of the Image component, but that sounds complicated and fragile. Is this possible in a responsive way with styling?

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

Demonstration code:

演示代码:

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

回答by Stanislau Buzunko

From React-native v0.50.0 <Image>with nested content is no longer supported. Use <ImageBackground>instead.

从 React-native v0.50.0 开始<Image>,不再支持嵌套内容。使用<ImageBackground>来代替。

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

回答by Oboo Cheng

Updated 29 Jun 2019

2019 年 6 月 29 日更新

Now([email protected]) there's a specific component to wrap elements as image background, ImageBackground. Go for the official documentation.

现在( [email protected]) 有一个特定的组件来包装元素作为图像背景,ImageBackground。去官方文档。

Following Gist has been changed.

以下要点已更改。



Original Answer

原答案

We can use <Image/>display images, and we can use it as a background-imagehack.

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

try this

试试这个

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

this gistis a full demo for your need.

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

or you can see it live at expo:

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

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

回答by Ozesh

Here is how I accomplished that:

这是我如何实现的:

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"
  }
});

Here is how it looks like :

这是它的样子:

enter image description here

在此处输入图片说明

回答by Keith Kurak

So the way you do this, as @ObooChin mentioned, is to use Image.getSize() to get the actual size of the image, then generate a height and width based on a) the maximum space you want the image to take up, and b) the aspect ratio of the actual image's dimensions.

所以你这样做的方式,正如@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 />
        )
    }
}

The attempt is still a bit rough, but I'm working on turning this into a library where you can specify max height, width, and the overlay you want to use, and it handles the rest: https://github.com/nudgeyourself/react-native-flexible-thumbnail.

尝试仍然有点粗糙,但我正在努力将其变成一个库,您可以在其中指定最大高度、宽度和要使用的叠加层,并处理其余部分:https: //github.com/轻推你自己/react-native-flexible-thumbnail