วิธีตั้งค่าสีพื้นหลังของมุมมองโปร่งใสใน React Native


151

นี่คือรูปแบบของมุมมองที่ฉันใช้

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

ปัจจุบันมีพื้นหลังสีขาว ฉันสามารถเปลี่ยน backgroundColor ได้ตามที่ฉันต้องการ'#343434'แต่ยอมรับเฉพาะค่าหกเหลี่ยมสูงสุด 6 ค่าสำหรับสีดังนั้นฉันจึงไม่สามารถให้ความทึบในแบบ'#00ffffff'นั้นได้ ฉันลองใช้ความทึบแบบนี้

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

แต่จะลดการเปิดเผยเนื้อหาของมุมมอง มีคำตอบไหม?

คำตอบ:


305

ใช้rgbaค่าสำหรับไฟล์backgroundColor.

ตัวอย่างเช่น,

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

ชุดนี้มันเป็นสีเทา 80% 0.8ความทึบแสงซึ่งได้มาจากทศนิยมทึบ ค่านี้จะได้อะไรจากการ0.01.0


ทำไมบนโลกถึงมีสี 8 บิตและอัลฟาเวลลอย?
duhaime

@duhaime ไม่แน่ใจว่าทำไมโดยเฉพาะ แต่ 8 บิตมีเหตุผลจากความทรงจำ (โดยเฉพาะในอดีต) ค่าอัลฟามีความหมายมากกว่าที่จะมี 0 และ 1 เป็นค่าต่ำสุดและสูงสุดเพื่อให้โปร่งใสเต็มที่หรือทึบแสง ตัวอย่างเช่นหากคุณต้องการให้บางสิ่งมีความโปร่งใส 25% คุณไม่ต้องคิดว่า 1 ใน 4 ของ 255 เป็นเท่าใด
kojow7

109

ต่อไปนี้ใช้งานได้ดี:

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

คุณยังสามารถลอง:

backgroundColor: 'transparent'

2
backgroundColor: 'โปร่งใส' เป็นวิธีที่ง่ายที่สุด
NathanL

29

ลองใช้วิธีนี้backgroundColor: '#00000000' มันจะตั้งค่าสีพื้นหลังเป็นแบบโปร่งใสตามด้วยรหัสฐานสิบหก


ด้วยเหตุผลบางประการตัวแปรนี้แสดงสีของผลลัพธ์ที่มีความทึบไม่ถูกต้อง ถ้าฉันจำไม่ผิดมันเป็นบั๊กใน RN จึงดีกว่าที่จะใช้rgbaวิธี.
Shyngys Kassymov

1
@ShyngysKassymov gist.github.com/lopspower/03fb1cc0ac9f32ef38f4ตรวจสอบสิ่งนี้
ʎzɐɹƆ

@ น่าสนใจที่สมเหตุสมผล ขอขอบคุณที่ชี้ให้เห็น! แต่ IMO มันง่ายกว่าที่จะใช้rgbaวิธีนี้ :)
Shyngys Kassymov

หมายความว่ารูปแบบควรเป็น #aarrggbb แทนหรือไม่
อาย Kassymov

ฉันหมายความว่าคุณสามารถใช้ hexavalue ในrrggbbaa.
ʎzɐɹƆ

7

น่าแปลกใจที่ไม่มีใครบอกเกี่ยวกับเรื่องนี้ซึ่งให้ความชัดเจน:

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

9
โซลูชันนี้กำหนดความทึบให้กับมุมมองทั้งหมดไม่ใช่แค่พื้นหลังส่งผลให้ลูก ๆ ทุกคนกลายเป็นกึ่งทึบเช่นกัน (ซึ่งจริง ๆ แล้วจะชี้ให้เห็นในคำถามดั้งเดิม)
Cool Soft

3

คุณควรตระหนักถึงความขัดแย้งในปัจจุบันที่เกิดขึ้นกับพื้นหลัง iOS และ RGBA

สรุป: Public React Native ในปัจจุบันแสดงคุณสมบัติเงาของเลเยอร์ iOS โดยตรงมากขึ้นหรือน้อยลงอย่างไรก็ตามมีปัญหาหลายประการเกี่ยวกับสิ่งนี้:

1) ประสิทธิภาพเมื่อใช้คุณสมบัติเหล่านี้ไม่ดีโดยค่าเริ่มต้น นั่นเป็นเพราะ iOS คำนวณเงาโดยรับมาสก์พิกเซลที่แน่นอนของมุมมองรวมถึงเนื้อหาที่ไม่แน่นอนและมุมมองย่อยทั้งหมดซึ่งใช้ CPU และ GPU มาก 2) คุณสมบัติเงาของ iOS ไม่ตรงกับไวยากรณ์หรือความหมายของมาตรฐาน CSS box-shadow และไม่น่าจะเป็นไปได้ที่จะนำไปใช้บน Android 3) เราไม่เปิดเผยไฟล์layer.shadowPathคุณสมบัติซึ่งมีความสำคัญอย่างยิ่งต่อการได้รับประสิทธิภาพที่ดีจากเงาของเลเยอร์

ความแตกต่างนี้ช่วยแก้ปัญหาหมายเลข 1) โดยใช้ค่าเริ่มต้น shadowPathที่ตรงกับเส้นขอบมุมมองสำหรับมุมมองที่มีพื้นหลังทึบแสง สิ่งนี้ช่วยเพิ่มประสิทธิภาพของเงาโดยการปรับให้เหมาะสมกับกรณีการใช้งานทั่วไป ฉันยังได้คืนสถานะการเผยแพร่สีพื้นหลังสำหรับมุมมองที่มีอุปกรณ์ประกอบฉากเงาซึ่งจะช่วยให้มั่นใจได้ว่าสถานการณ์กรณีที่ดีที่สุดนี้จะเกิดขึ้นบ่อยขึ้น

สำหรับมุมมองที่มีพื้นหลังโปร่งใสอย่างชัดเจนเงาจะยังคงทำงานเหมือนเดิม ( shadowPathจะถูกปล่อยทิ้งไว้โดยไม่ได้ตั้งค่าและเงาจะได้มาจากพิกเซลของมุมมองและมุมมองย่อยทั้งหมด) อย่างไรก็ตามนี่เป็นเส้นทางที่เลวร้ายที่สุดสำหรับประสิทธิภาพดังนั้นคุณควรหลีกเลี่ยงหากไม่จำเป็นจริงๆการสนับสนุนสำหรับสิ่งนี้อาจถูกปิดใช้งานโดยค่าเริ่มต้นในอนาคตหรือถูกยกเลิกทั้งหมด

สำหรับภาพโปร่งแสงขอแนะนำให้คุณอบเงาลงในภาพนั้นเองหรือใช้กลไกอื่นเพื่อสร้างเงาล่วงหน้า สำหรับเงาข้อความคุณควรใช้คุณสมบัติ textShadow ซึ่งทำงานข้ามแพลตฟอร์มและมีประสิทธิภาพที่ดีกว่ามาก

ปัญหาหมายเลข 2) จะได้รับการแก้ไขในอนาคตที่แตกต่างกันโดยอาจเปลี่ยนชื่อคุณสมบัติ iOS shadowXXX เป็น boxShadowXXX และเปลี่ยนไวยากรณ์และความหมายให้ตรงกับมาตรฐาน CSS

ปัญหาหมายเลข 3) ตอนนี้ส่วนใหญ่เป็นที่สงสัยเนื่องจากเราสร้าง shadowPath โดยอัตโนมัติ ในอนาคตเราอาจจัดเตรียมเสาเฉพาะสำหรับ iOS เพื่อกำหนดเส้นทางอย่างชัดเจนหากมีความต้องการในการควบคุมเงาที่แม่นยำยิ่งขึ้น

บทวิจารณ์โดย: weicool

คอมมิต: https://github.com/facebook/react-native/commit/e4c53c28aea7e067e48f5c8c0100c7cafc031b06


-1

นี่คือวิธีแก้ปัญหาของฉันสำหรับโมดอลที่สามารถแสดงผลบนหน้าจอใดก็ได้และเริ่มต้นใน 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 เรนเดอร์และนำเข้า

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

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

และใช้จากส่วนประกอบใดก็ได้

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

หวังว่าฉันจะช่วยพวกคุณได้บ้างฉันใช้โครงสร้างที่คล้ายกันมากสำหรับการแจ้งเตือนในแอป

มีความสุขในการเขียนโค้ด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.