How to set background color of view transparent in React Native
React NativeReact Native Problem Overview
This is the style of the view that i have used
backCover: {
position: 'absolute',
marginTop: 20,
top: 0,
bottom: 0,
left: 0,
right: 0,
}
Currently it has a white background. I can change the backgroundColor as i want like '#343434'
but it accepts only max 6 hexvalue for color so I cannot give opacity on that like '#00ffffff'
. I tried using opacity like this
backCover: {
position: 'absolute',
marginTop: 20,
top: 0,
bottom: 0,
left: 0,
right: 0,
opacity: 0.5,
}
but it reduces visibility of view's content. So any answers?
React Native Solutions
Solution 1 - React Native
rgba
value for the backgroundColor
.
Use For example,
backgroundColor: 'rgba(52, 52, 52, 0.8)'
This sets it to a grey color with 80% opacity, which is derived from the opacity decimal, 0.8
. This value can be anything from 0.0
to 1.0
.
Solution 2 - React Native
The following works fine:
backgroundColor: 'rgba(52, 52, 52, alpha)'
You could also try:
backgroundColor: 'transparent'
Solution 3 - React Native
Try this backgroundColor: '#00000000'
it will set background color to transparent, it follows #rrggbbaa hex codes
Solution 4 - React Native
Surprisingly no one told about this, which provides some !clarity:
style={{
backgroundColor: 'white',
opacity: 0.7
}}
Solution 5 - React Native
Try to use transparent attribute value for making transparent background color.
backgroundColor: 'transparent'
Solution 6 - React Native
You should be aware of the current conflicts that exists with iOS and RGBA backgrounds.
> Summary: public React Native currently exposes the iOS layer shadow
> properties more-or-less directly, however there are a number of
> problems with this:
>
> 1) Performance when using these properties is poor by default. That's
> because iOS calculates the shadow by getting the exact pixel mask of
> the view, including any tranlucent content, and all of its subviews,
> which is very CPU and GPU-intensive. 2) The iOS shadow properties do
> not match the syntax or semantics of the CSS box-shadow standard, and
> are unlikely to be possible to implement on Android. 3) We don't
> expose the layer.shadowPath
property, which is crucial to getting
> good performance out of layer shadows.
>
> This diff solves problem number 1) by implementing a default
> shadowPath
that matches the view border for views with an opaque
> background. This improves the performance of shadows by optimizing for
> the common usage case. I've also reinstated background color
> propagation for views which have shadow props - this should help
> ensure that this best-case scenario occurs more often.
>
> For views with an explicit transparent background, the shadow will
> continue to work as it did before ( shadowPath
will be left unset,
> and the shadow will be derived exactly from the pixels of the view and
> its subviews). This is the worst-case path for performance, however,
> so you should avoid it unless absolutely necessary. Support for this
> may be disabled by default in future, or dropped altogether.
>
> For translucent images, it is suggested that you bake the shadow into
> the image itself, or use another mechanism to pre-generate the shadow.
> For text shadows, you should use the textShadow properties, which work
> cross-platform and have much better performance.
>
> Problem number 2) will be solved in a future diff, possibly by
> renaming the iOS shadowXXX properties to boxShadowXXX, and changing
> the syntax and semantics to match the CSS standards.
>
> Problem number 3) is now mostly moot, since we generate the shadowPath
> automatically. In future, we may provide an iOS-specific prop to set
> the path explicitly if there's a demand for more precise control of
> the shadow.
>
> Reviewed By: weicool
Commit: https://github.com/facebook/react-native/commit/e4c53c28aea7e067e48f5c8c0100c7cafc031b06
Solution 7 - React Native
Adding reference of React-Native Version 0.64
Named colors
> In React Native you can also use color name strings as values. Note: React Native only supports lowercase color names. Uppercase color names are not supported. transparent# This is a shortcut for rgba(0,0,0,0), same like in CSS3.
Hence you can do this:
background: {
backgroundColor: 'transparent'
},
Which is a shortcut of :
background: {
backgroundColor: 'rgba(0,0,0,0)'
},
Solution 8 - React Native
The best way to use is hex code rrggbbaa but it should be in hex.
Eg: 50% opacity means 256/2 then convert that value in HEX that will be 80 so use #00000080
80 means 50% transparent here
Solution 9 - React Native
In case you have hex color, you can convert it to rgba and set the opacity there:
const hexToRgbA = (hex, opacity) => {
let c;
if (/^#([A-Fa-f0-9]{3}){1,2}$/.test(hex)) {
c = hex.substring(1).split('');
if (c.length === 3) {
c = [c[0], c[0], c[1], c[1], c[2], c[2]];
}
c = `0x${c.join('')}`;
return `rgba(${[(c >> 16) & 255, (c >> 8) & 255, c & 255].join(',')},${opacity})`;
}
throw new Error('Bad Hex');
};
const color = '#1f8b7f'; // could be a variable
return (
<View style={{ backgroundColor: hexToRgbA(color, 0.1) }} />
)
Solution 10 - React Native
Here is my solution to a modal that can be rendered on any screen and initialized in App.tsx
ModalComponent.tsx
import React, { Component } from 'react';
import { Modal, Text, TouchableHighlight, View, StyleSheet, Platform } from 'react-native';
import EventEmitter from 'events';
// I keep localization files for strings and device metrics like height and width which are used for styling
import strings from '../../config/strings';
import metrics from '../../config/metrics';
const emitter = new EventEmitter();
export const _modalEmitter = emitter
export class ModalView extends Component {
state: {
modalVisible: boolean,
text: string,
callbackSubmit: any,
callbackCancel: any,
animation: any
}
constructor(props) {
super(props)
this.state = {
modalVisible: false,
text: "",
callbackSubmit: (() => {}),
callbackCancel: (() => {}),
animation: new Animated.Value(0)
}
}
componentDidMount() {
_modalEmitter.addListener(strings.modalOpen, (event) => {
var state = {
modalVisible: true,
text: event.text,
callbackSubmit: event.onSubmit,
callbackCancel: event.onClose,
animation: new Animated.Value(0)
}
this.setState(state)
})
_modalEmitter.addListener(strings.modalClose, (event) => {
var state = {
modalVisible: false,
text: "",
callbackSubmit: (() => {}),
callbackCancel: (() => {}),
animation: new Animated.Value(0)
}
this.setState(state)
})
}
componentWillUnmount() {
var state = {
modalVisible: false,
text: "",
callbackSubmit: (() => {}),
callbackCancel: (() => {})
}
this.setState(state)
}
closeModal = () => {
_modalEmitter.emit(strings.modalClose)
}
startAnimation=()=>{
Animated.timing(this.state.animation, {
toValue : 0.5,
duration : 500
}).start()
}
body = () => {
const animatedOpacity ={
opacity : this.state.animation
}
this.startAnimation()
return (
<View style={{ height: 0 }}>
<Modal
animationType="fade"
transparent={true}
visible={this.state.modalVisible}>
// render a transparent gray background over the whole screen and animate it to fade in, touchable opacity to close modal on click out
<Animated.View style={[styles.modalBackground, animatedOpacity]} >
<TouchableOpacity onPress={() => this.closeModal()} activeOpacity={1} style={[styles.modalBackground, {opacity: 1} ]} >
</TouchableOpacity>
</Animated.View>
// render an absolutely positioned modal component over that background
<View style={styles.modalContent}>
<View key="text_container">
<Text>{this.state.text}?</Text>
</View>
<View key="options_container">
// keep in mind the content styling is very minimal for this example, you can put in your own component here or style and make it behave as you wish
<TouchableOpacity
onPress={() => {
this.state.callbackSubmit();
}}>
<Text>Confirm</Text>
</TouchableOpacity>
<TouchableOpacity
onPress={() => {
this.state.callbackCancel();
}}>
<Text>Cancel</Text>
</TouchableOpacity>
</View>
</View>
</Modal>
</View>
);
}
render() {
return this.body()
}
}
// to center the modal on your screen
// top: metrics.DEVICE_HEIGHT/2 positions the top of the modal at the center of your screen
// however you wanna consider your modal's height and subtract half of that so that the
// center of the modal is centered not the top, additionally for 'ios' taking into consideration
// the 20px top bunny ears offset hence - (Platform.OS == 'ios'? 120 : 100)
// where 100 is half of the modal's height of 200
const styles = StyleSheet.create({
modalBackground: {
height: '100%',
width: '100%',
backgroundColor: 'gray',
zIndex: -1
},
modalContent: {
position: 'absolute',
alignSelf: 'center',
zIndex: 1,
top: metrics.DEVICE_HEIGHT/2 - (Platform.OS == 'ios'? 120 : 100),
justifyContent: 'center',
alignItems: 'center',
display: 'flex',
height: 200,
width: '80%',
borderRadius: 27,
backgroundColor: 'white',
opacity: 1
},
})
App.tsx render and import
import { ModalView } from './{your_path}/ModalComponent';
render() {
return (
<React.Fragment>
<StatusBar barStyle={'dark-content'} />
<AppRouter />
<ModalView />
</React.Fragment>
)
}
and to use it from any component
SomeComponent.tsx
import { _modalEmitter } from './{your_path}/ModalComponent'
// Some functions within your component
showModal(modalText, callbackOnSubmit, callbackOnClose) {
_modalEmitter.emit(strings.modalOpen, { text: modalText, onSubmit: callbackOnSubmit.bind(this), onClose: callbackOnClose.bind(this) })
}
closeModal() {
_modalEmitter.emit(strings.modalClose)
}
Hope I was able to help some of you, I used a very similar structure for in-app notifications
Happy coding