Come impostare il colore di sfondo della vista trasparente in React Native


139

Questo è lo stile della vista che ho usato

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

Attualmente ha uno sfondo bianco. Posso cambiare il '#343434'colore di sfondo come voglio, ma accetta solo un massimo di 6 valori esadecimali per il colore, quindi non posso dare opacità su quel tipo '#00ffffff'. Ho provato a usare l'opacità in questo modo

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

ma riduce la visibilità del contenuto della vista. Quindi qualche risposta?

Risposte:


288

Usa rgbavalore per backgroundColor.

Per esempio,

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

Questo imposta ad un colore grigio con 80% di opacità, che è derivato dal decimale opacità, 0.8. Questo valore può essere qualsiasi da 0.0a 1.0.


perché mai i colori val 8 bit e i valori alfa val galleggiano?
duhaime,

@duhaime, non sono sicuro del perché in particolare, ma 8 bit ha senso dal punto di vista della memoria (soprattutto storicamente). I valori alfa hanno più senso avere 0 e 1 come minimo e massimo per completamente trasparente o completamente opaco. Ad esempio, se si desidera che qualcosa sia trasparente al 25%, non si vuole capire che cosa sia 1/4 di 255.
kojow7,

104

Di seguito funziona bene:

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

Puoi anche provare:

backgroundColor: 'transparent'

2
backgroundColor: 'trasparente' è di gran lunga la soluzione più semplice.
NathanL

27

Prova questo backgroundColor: '#00000000' imposterà il colore di sfondo su trasparente, segue i codici esadecimali #rrggbbaa


Per qualche motivo, questa variante mostra il colore del risultato con l'opacità in modo errato. Se non sbaglio è un bug in RN. Quindi meglio usare il rgbamodo.
Shyngys Kassymov,

1
@ShyngysKassymov gist.github.com/lopspower/03fb1cc0ac9f32ef38f4 controlla questo
Oo

@Oo interessante, ha senso. Grazie per la segnalazione! Ma IMO è più facile da usare rgba:)
Shyngys Kassymov il

significa che il formato dovrebbe essere invece #aarrggbb?
Shyngys Kassymov,

Volevo dire che puoi usare hexavalue in rrggbbaa.
Oo

3

È necessario essere consapevoli degli attuali conflitti esistenti con gli sfondi iOS e RGBA.

Riepilogo: pubblico React Native attualmente espone le proprietà dell'ombra del livello iOS più o meno direttamente, tuttavia ci sono una serie di problemi con questo:

1) Le prestazioni quando si utilizzano queste proprietà sono scarse per impostazione predefinita. Questo perché iOS calcola l'ombra ottenendo l'esatta maschera pixel della vista, incluso qualsiasi contenuto tranlucent e tutte le sue visualizzazioni secondarie, che richiedono molta CPU e GPU. 2) Le proprietà dell'ombra iOS non corrispondono alla sintassi o alla semantica dello standard box-shadow CSS e è improbabile che possano essere implementate su Android. 3) Non esponiamo la layer.shadowPathproprietà, che è fondamentale per ottenere buone prestazioni dalle ombre dei livelli.

Questo differ risolve il problema numero 1) implementando un valore predefinito shadowPathche corrisponde al bordo della vista per le viste con uno sfondo opaco. Ciò migliora le prestazioni delle ombre ottimizzando per il caso d'uso comune. Ho anche ripristinato la propagazione del colore di sfondo per le viste che hanno puntelli d'ombra - questo dovrebbe aiutare a garantire che questo scenario migliore si verifichi più spesso.

Per le viste con uno sfondo trasparente esplicito, l'ombra continuerà a funzionare come prima ( shadowPathrimarrà non impostata e l'ombra verrà derivata esattamente dai pixel della vista e dalle sue visualizzazioni secondarie). Questo è il percorso peggiore per le prestazioni, tuttavia, quindi dovresti evitarlo a meno che non sia assolutamente necessario. Il supporto per questo potrebbe essere disabilitato per impostazione predefinita in futuro o essere abbandonato del tutto.

Per le immagini traslucide, si consiglia di cuocere l'ombra nell'immagine stessa o utilizzare un altro meccanismo per pre-generare l'ombra. Per le ombre di testo, dovresti usare le proprietà textShadow, che funzionano su più piattaforme e offrono prestazioni molto migliori.

Il problema numero 2) verrà risolto in un futuro diff, eventualmente rinominando le proprietà di iOS shadowXXX in boxShadowXXX e modificando la sintassi e la semantica in modo che corrispondano agli standard CSS.

Il problema numero 3) ora è per lo più controverso, poiché generiamo automaticamente shadowPath. In futuro, potremmo fornire un supporto specifico per iOS per impostare esplicitamente il percorso se c'è una richiesta per un controllo più preciso dell'ombra.

Recensione di: weicool

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


2

Sorprendentemente nessuno ne ha parlato, il che fornisce un po 'di chiarezza:

style={{
backgroundColor: 'white',
opacity: 0.7
}}

6
Questa soluzione definisce l'opacità dell'intera vista, non solo del suo sfondo, facendo sì che anche tutti i suoi figli diventino semi-opachi (questo è in realtà sottolineato nella domanda originale)
Cool Soft

-1

Ecco la mia soluzione per un modale che può essere renderizzato su qualsiasi schermo e inizializzato 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 esegue il rendering e l'importazione

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

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

e per usarlo da qualsiasi 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)
}

Spero di essere stato in grado di aiutare alcuni di voi, ho usato una struttura molto simile per le notifiche in-app

Buona codifica

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.