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
Overlay button on top of Image in React Native
提问by Keith Kurak
I'm trying to achieve the following effect in React Native:
我正在尝试在 React Native 中实现以下效果:
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 中的样子:
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 :
这是它的样子:
回答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。


