Cara mengatur warna latar belakang tampilan transparan di React Native

151

Ini adalah gaya tampilan yang saya gunakan

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

Saat ini memiliki latar belakang putih. Saya dapat mengubah backgroundColor sesuka saya '#343434'tetapi hanya menerima max 6 hexvalue untuk warna jadi saya tidak bisa memberikan opacity pada yang seperti itu '#00ffffff'. Saya mencoba menggunakan opacity seperti ini

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

tetapi mengurangi visibilitas konten tampilan. Jadi ada jawaban?

JEROM JOY
sumber

Jawaban:

305

Gunakan rgbanilai untuk backgroundColor.

Sebagai contoh,

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

Ini menyetelnya ke warna abu-abu dengan opasitas 80%, yang diturunkan dari desimal opasitas 0.8,. Nilai ini bisa apa saja mulai dari 0.0sampai 1.0.

dieuvn3b
sumber
mengapa color vals 8 bit dan alpha vals mengapung?
duhaime
@ duhaime, tidak yakin mengapa secara khusus, tetapi 8-bit masuk akal dari pengertian memori (terutama secara historis). Nilai alfa lebih masuk akal untuk memiliki 0 dan 1 sebagai min dan max untuk sepenuhnya transparan atau sepenuhnya buram. Misalnya, jika Anda ingin sesuatu menjadi 25% transparan, Anda tidak ingin mencari tahu 1/4 dari 255.
kojow7
109

Berikut ini berfungsi dengan baik:

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

Anda juga bisa mencoba:

backgroundColor: 'transparent'
JEROM JOY
sumber
2
backgroundColor: 'transparan' sejauh ini merupakan solusi termudah.
NathanL
29

Coba ini backgroundColor: '#00000000' akan mengatur warna latar belakang menjadi transparan, ini mengikuti kode hex #rrggbbaa

Tharzeez
sumber
Untuk beberapa alasan, varian ini salah menampilkan warna hasil dengan opasitas. Jika saya tidak salah itu bug di RN. Karena itu lebih baik gunakan rgbacara tersebut.
Shyngys Kassymov
1
@ShyngysKassymov gist.github.com/lopspower/03fb1cc0ac9f32ef38f4 periksa ini
ʎzɐɹƆ
@Oo menarik, itu masuk akal. Terima kasih telah menunjukkannya! Tapi IMO lebih mudah menggunakan rgbacara :)
Shyngys Kassymov
apakah itu berarti bahwa formatnya harus #aarrggbb?
Shyngys Kassymov
Maksud saya, Anda dapat menggunakan nilai hex dalam rrggbbaa.
ʎzɐɹƆ
7

Anehnya tidak ada yang memberi tahu tentang ini, yang memberikan beberapa kejelasan:

style={{
backgroundColor: 'white',
opacity: 0.7
}}
Antonin GAVREL
sumber
9
Solusi ini menentukan opasitas ke seluruh tampilan, bukan hanya latar belakangnya, sehingga semua turunannya menjadi semi-buram juga (yang sebenarnya ditunjukkan dalam pertanyaan awal)
Cool Soft
3

Anda harus menyadari konflik saat ini yang ada dengan latar belakang iOS dan RGBA.

Rangkuman: public React Native saat ini mengekspos properti iOS layer shadow lebih atau kurang secara langsung, namun ada sejumlah masalah dengan ini:

1) Kinerja saat menggunakan properti ini buruk secara default. Itu karena iOS menghitung bayangan dengan mendapatkan tampilan topeng piksel yang tepat, termasuk konten transparan apa pun, dan semua subviewnya, yang sangat intensif CPU dan GPU. 2) Properti bayangan iOS tidak cocok dengan sintaks atau semantik standar kotak-bayangan CSS, dan kemungkinan besar tidak dapat diterapkan di Android. 3) Kami tidak mengekspos layer.shadowPathproperti, yang sangat penting untuk mendapatkan kinerja yang baik dari bayangan lapisan.

Perbedaan ini memecahkan masalah nomor 1) dengan menerapkan default shadowPathyang cocok dengan batas tampilan untuk tampilan dengan latar belakang buram. Ini meningkatkan kinerja bayangan dengan mengoptimalkan kasus penggunaan umum. Saya juga telah memulihkan propagasi warna latar belakang untuk tampilan yang memiliki alat peraga bayangan - ini akan membantu memastikan bahwa skenario kasus terbaik ini lebih sering terjadi.

Untuk tampilan dengan latar belakang transparan eksplisit, bayangan akan terus bekerja seperti sebelumnya ( shadowPathtidak disetel, dan bayangan akan diturunkan persis dari piksel tampilan dan subviewnya). Namun, ini adalah jalur kasus terburuk untuk kinerja, jadi Anda harus menghindarinya kecuali benar-benar diperlukan. Dukungan untuk ini mungkin dinonaktifkan secara default di masa mendatang, atau dihentikan sama sekali.

Untuk gambar tembus cahaya, disarankan agar Anda memanggang bayangan ke dalam gambar itu sendiri, atau menggunakan mekanisme lain untuk menghasilkan bayangan sebelumnya. Untuk bayangan teks, Anda harus menggunakan properti textShadow, yang bekerja lintas platform dan memiliki kinerja yang jauh lebih baik.

Masalah nomor 2) akan diselesaikan di diff masa depan, mungkin dengan mengganti nama properti iOS shadowXXX menjadi boxShadowXXX, dan mengubah sintaks dan semantik agar sesuai dengan standar CSS.

Masalah nomor 3) sekarang sebagian besar diperdebatkan, karena kita menghasilkan shadowPath secara otomatis. Di masa mendatang, kami mungkin menyediakan properti khusus iOS untuk menyetel jalur secara eksplisit jika ada permintaan untuk kontrol bayangan yang lebih tepat.

Diulas oleh: weicool

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

Matías Fork
sumber
-1

Berikut adalah solusi saya untuk modal yang dapat ditampilkan di layar apa pun dan diinisialisasi di 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 
    },
})

Render dan impor App.tsx

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

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

dan menggunakannya dari komponen apa pun

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

Semoga saya dapat membantu beberapa dari Anda, saya menggunakan struktur yang sangat mirip untuk pemberitahuan dalam aplikasi

Selamat membuat kode

Nikola G. Tachev
sumber