Cómo establecer el color de fondo de la vista transparente en React Native

139

Este es el estilo de la vista que he usado

backCover: {
  position: 'absolute',
  marginTop: 20,
  top: 0,
  bottom: 0,
  left: 0,
  right: 0,
}

Actualmente tiene un fondo blanco. Puedo cambiar el backgroundColor como quiera, '#343434'pero solo acepta un máximo de 6 valores hexadecimales para el color, por lo que no puedo dar opacidad en ese me gusta '#00ffffff'. Intenté usar opacidad como esta

backCover: {
  position: 'absolute',
  marginTop: 20,
  top: 0,
  bottom: 0,
  left: 0,
  right: 0,
  opacity: 0.5,
}

pero reduce la visibilidad del contenido de la vista. Entonces, ¿alguna respuesta?

JEROM JOY
fuente

Respuestas:

288

Utilice el rgbavalor para el backgroundColor.

Por ejemplo,

backgroundColor: 'rgba(52, 52, 52, 0.8)'

Esto establece a un color gris con un 80% de opacidad, que se deriva de la decimal opacidad, 0.8. Este valor puede ser cualquier cosa desde 0.0hasta 1.0.

dieuvn3b
fuente
¿Por qué demonios los flotadores de color vals de 8 bits y alfa vals?
duhaime
@duhaime, no estoy seguro de por qué específicamente, pero 8 bits tiene sentido desde el sentido de la memoria (especialmente históricamente). Los valores alfa tienen más sentido tener 0 y 1 como mínimo y máximo para totalmente transparente u opaco. Por ejemplo, si desea que algo tenga un 25% de transparencia, no quiere saber qué es 1/4 de 255.
kojow7
104

Lo siguiente funciona bien:

backgroundColor: 'rgba(52, 52, 52, alpha)'

También puedes probar:

backgroundColor: 'transparent'
JEROM JOY
fuente
2
backgroundColor: 'transparente' es, con mucho, la solución más fácil.
NathanL
27

Pruebe esto backgroundColor: '#00000000' , establecerá el color de fondo en transparente, sigue los códigos hexadecimales #rrggbbaa

Tharzeez
fuente
Por alguna razón, esta variante muestra incorrectamente el color resultante con opacidad. Si no me equivoco, es un error en RN. Por lo tanto, mejor usar el rgbacamino.
Shyngys Kassymov
1
@ShyngysKassymov gist.github.com/lopspower/03fb1cc0ac9f32ef38f4 revisa esto
Oo
@Oo interesante, eso tiene sentido. Gracias por señalar! Pero en mi opinión, es más fácil de usar rgba:)
Shyngys Kassymov
¿significa que el formato debería ser #aarrggbb en su lugar?
Shyngys Kassymov
Quise decir que puedes usar el hexavalor rrggbbaa.
Oo
3

Debe tener en cuenta los conflictos actuales que existen con los fondos de iOS y RGBA.

Resumen: public React Native actualmente expone las propiedades de sombra de la capa de iOS más o menos directamente, sin embargo, hay una serie de problemas con esto:

1) El rendimiento cuando se usan estas propiedades es pobre por defecto. Esto se debe a que iOS calcula la sombra al obtener la máscara de píxeles exacta de la vista, incluido cualquier contenido translúcido, y todas sus subvistas, que requieren mucha CPU y GPU. 2) Las propiedades de sombra de iOS no coinciden con la sintaxis o la semántica del estándar CSS-shadow box y es poco probable que se puedan implementar en Android. 3) No exponemos la layer.shadowPathpropiedad, que es crucial para obtener un buen rendimiento de las sombras de capa.

Esta diferencia resuelve el problema número 1) mediante la implementación de un valor predeterminado shadowPathque coincide con el borde de la vista para vistas con un fondo opaco. Esto mejora el rendimiento de las sombras mediante la optimización para el caso de uso común. También he restablecido la propagación del color de fondo para las vistas que tienen accesorios de sombra; esto debería ayudar a garantizar que este mejor escenario ocurra con más frecuencia.

Para las vistas con un fondo transparente explícito, la sombra continuará funcionando como lo hizo antes (se shadowPathdejará sin configurar y la sombra se derivará exactamente de los píxeles de la vista y sus subvistas). Sin embargo, este es el peor camino para el rendimiento, por lo que debe evitarlo a menos que sea absolutamente necesario. El soporte para esto puede deshabilitarse de manera predeterminada en el futuro o dejarse de lado por completo.

Para imágenes translúcidas, se sugiere que hornee la sombra en la imagen misma, o use otro mecanismo para pregenerar la sombra. Para las sombras de texto, debe usar las propiedades textShadow, que funcionan multiplataforma y tienen un rendimiento mucho mejor.

El problema número 2) se resolverá en una diferencia futura, posiblemente cambiando el nombre de las propiedades shadowXXX de iOS a boxShadowXXX y cambiando la sintaxis y la semántica para que coincidan con los estándares CSS.

El problema número 3) ahora es mayormente discutible, ya que generamos shadowPath automáticamente. En el futuro, podemos proporcionar un accesorio específico para iOS para establecer el camino explícitamente si existe una demanda de un control más preciso de la sombra.

Revisado por: weicool

Comprometerse: https://github.com/facebook/react-native/commit/e4c53c28aea7e067e48f5c8c0100c7cafc031b06

Tenedor Matías
fuente
2

Sorprendentemente, nadie habló de esto, lo que proporciona cierta claridad:

style={{
backgroundColor: 'white',
opacity: 0.7
}}
Antonin GAVREL
fuente
66
Esta solución define la opacidad de toda la vista, no solo su fondo, lo que hace que todos sus hijos se vuelvan semi opacos también (eso se señala en la pregunta original)
Cool Soft
-1

Aquí está mi solución a un modal que se puede representar en cualquier pantalla e inicializar en 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 e importación

import { ModalView } from './{your_path}/ModalComponent';

render() {
    return (
        <React.Fragment>
            <StatusBar barStyle={'dark-content'} />
            <AppRouter />
            <ModalView />
        </React.Fragment>
    )
}

y usarlo desde cualquier componente

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

Espero haber podido ayudar a algunos de ustedes, utilicé una estructura muy similar para las notificaciones en la aplicación

Codificación feliz

Nikola G. Tachev
fuente