[英]Overlay button on top of Image in React Native
我正在尝试在 React Native 中实现以下效果:
图像的角落有一个按钮。 无论图像的大小或纵横比如何,该按钮始终位于图像的角落内,并且图像的任何部分都不会被剪裁(它总是按比例缩小以完全适合一个框)。
我在 React Native 中遇到的问题是 Image 组件的大小并不总是与缩小的图像大小匹配。 如果我将图像的高度固定为 300,设置 flex 1 使图像的宽度扩展以填充其内容,并且图像是肖像,图像组件具有容器的全宽,但组件内的图像将具有宽度要小得多。 因此,让视图覆盖另一个视图的典型方法并不像我希望的那样工作 - 我的覆盖层还覆盖了图像周围的填充,并且按钮(锚定到角落)出现在图像之外。
这是在 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"
}
});
这是它的样子:
现在( 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.