使用React Native实现图片叠加文字并降低透明度

21

我试图在一张图像上叠加一个标题,并使图像以较低的不透明度变暗。然而,不透明度效果也会影响覆盖的文本,使其变暗。有什么解决办法吗?以下是它的外观:

enter image description here

这是自定义组件 (文章预览),上面的图像是文章预览组件的一行的代码:

//component for article preview touchable image
/* will require the following
- rss feed and api
- user's keyword interests from parse In home.js
- parse db needs to be augmented to include what they heart
- parse db needs to be augmented to include what they press on (like google news)
*/
var React = require('react-native');
var {
  View, 
  StyleSheet, 
  Text, 
  Image, 
  TouchableHighlight, 
} = React;

//dimensions
var Dimensions = require('Dimensions');
var window = Dimensions.get('window');
var ImageButton = require('../../common/imageButton');
var KeywordBox = require('../../authentication/onboarding/keyword-box');

//additional libraries

module.exports = React.createClass({
  //onPress function that triggers when button pressed
  //this.props.text is property that can be dynamically filled within button 
  /* following props:
    - source={this.props.source}
    - onPress={this.props.onPress}
    - {this.props.text}
    - {this.props.heartText}
    - key={this.props.key} 
    - text={this.props.category} 
    - this.props.selected
  */
  render: function() {
    return (
      <TouchableHighlight 
        underlayColor={'transparent'}
        onPress={this.props.onPress} >
          <Image 
            source={this.props.source} 
            style={[styles.articlePreview, this.border('red')]}>
                  <View style={[styles.container, this.border('organge')]}>
                      <View style={[styles.header, this.border('blue')]}>
                          <Text style={[styles.previewText]}>{this.props.text}</Text>
                      </View>
                      <View style={[styles.footer, this.border('white')]}>
                        <View style={[styles.heartRow, this.border('black')]}>
                          <ImageButton
                              style={[styles.heartBtn, , this.border('red')]}
                              resizeMode={'contain'}
                              onPress={this.onHeartPress}
                              source={require('../../img/heart_btn.png')} />
                          <Text style={[styles.heartText]}>{this.props.heartText + ' favorites'}</Text>
                        </View>
                          <KeywordBox 
                              style={[styles.category, this.border('blue')]}
                              key={this.props.key} 
                              text={this.props.category} 
                              onPress={this.props.categoryPress}
                              selected={this.props.selected} />
                      </View>
                  </View>
          </Image>
      </TouchableHighlight>
    );
  }, 
  onHeartPress: function() {
    //will move this function to a general module
  }, 
  border: function(color) {
      return {
        //borderColor: color, 
        //borderWidth: 4,
      } 
   },
});

var styles = StyleSheet.create({
  heartText: {
    color: 'white', 
    fontSize: 12, 
    fontWeight: 'bold',
    alignSelf: 'center', 
    marginLeft: 5, 
    fontFamily: 'SFCompactText-Medium'
  }, 
  heartRow: {
    flexDirection: 'row', 
    justifyContent: 'space-around', 
    alignSelf: 'center', 
    justifyContent: 'center', 
  }, 
  heartBtn: {
    height: (92/97)*(window.width/13), 
    width: window.width/13, 
    alignSelf:'center', 
  }, 
  category: {
    fontFamily: 'Bebas Neue', 
    fontSize: 10,
    fontWeight: 'bold'
  }, 
  header: {
    flex: 3, 
    alignItems: 'center', 
    justifyContent: 'space-around', 
    marginTop: window.height/30,
  }, 
  footer: {
    flex: 1, 
    flexDirection: 'row', 
    justifyContent: 'space-between', 
    alignItems: 'center', 
    margin: window.height/50,
  }, 
  container: {
    flex: 1, 
    backgroundColor: 'black', 
    opacity: 0.6, 
  }, 
  articlePreview: {
    flex: 1, 
    height: window.height/3.2, 
    width: window.width, 
    flexDirection: 'column'
  }, 
  previewText: {
    fontFamily: 'Bebas Neue', 
    fontSize: 23,
    color: 'white', 
    alignSelf: 'center', 
    textAlign: 'center', 
    margin: 5, 
    position: 'absolute',
    top: 0,
    right: 0,
    bottom: 0,
    left: 0
  }, 

});
4个回答

26

尝试更改容器的样式为

container: {
 flex: 1, 
 backgroundColor: 'rgba(0,0,0,.6)'
},

这就是诀窍。如果 rgba() 不起作用,应该将 React Native 更新到0.16或更高版本。 - Samuli Hakoniemi

6

不要在整个ImageBackground元素上应用不透明度,而是在图像本身上实现它。例如:

<ImageBackground style={styles.imageContainer}
                 imageStyle={{ opacity: 0.5 }}
                 source={require('../assets/images/background.png')}>
                <View style={styles.welcomeContainer}>
                    <Image source={require('../assets/images/zeptagram-logo.png')} style={styles.welcomeImage} />
                </View>
            </ImageBackground>

超级厉害的方法.. 简单而且最好 - gaurav2141
通常希望使用<ImageBackground>作为其他组件的背景。在这种情况下,Nader的答案也会对<ImageBackground>的子元素进行着色,即使它们是同级的。通过imageStyle属性设置不透明度就不会有这个问题。 在我看来,这是最好的答案。 - mikeymop

3

透明度会影响整个视图。尝试使用两个视图,一个绝对定位并包含图像,另一个包含文本和按钮内容。

您可以使用 position: "absolute", top: 0, left: 0 绝对定位一个视图。


我今天会调查一下 - 看起来我只是改变了UI以避免整个问题,并采用了Google新闻UX路线。 - Robert Tomas G IV
你有什么运气吗? - Dan G Nelson
我最终做的是彻底改变了视图,使其类似于Google新闻。 - Robert Tomas G IV

3

我使用图像标签内的背景来解决我的工作问题,它运行良好。 就像这样

<Image source={require('./img/2.jpg')} style=
              {{height:deviceRowHeight,width:deviceWidth}}>
    <View style={{backgroundColor:'rgba(0,0,0,.6)',
                 height:deviceRowHeight,width:deviceWidth}}>
         <Text> Test Text </Text>
    </View>
</Image>

那个背景颜色rgba对于内容修复非常有用。<Image style={[{...StyleSheet.absoluteFillObject}, {flex: 1, height: 500, borderColor: 'transparent'}]} source={{uri: this.state.imageBackground}} /> <Content style={{flex: 1, backgroundColor:'rgba(0,0,0,.6)'}}> ... </Content> - Tiberiu Mihai
3
<Image> 组件不能包含子元素。 - Jago
@Jago 你可以使用 https://reactnative.dev/docs/imagebackground - HeWhoBuilds

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接