首页 > 解决方案 > React-native:除非更改状态,否则绝对定位的组件不会完全渲染

问题描述

我有一个包含多个组件的屏幕,一些具有相对定位,一些具有绝对定位。打开屏幕时,绝对定位的组件不会一直到达它们最终的正确位置或大小。它们出现在屏幕上,但出现在错误的位置和大小。只有通过按下按钮更改状态,组件才能完成渲染。这是下面屏幕的简化版本:

在此处输入图像描述

左侧的屏幕截图具有绝对定位的菜单图标(右上角的 3 条水平线),但尚未完全处于正确位置。只有在我通过按下可触摸区域更改状态后,右侧的屏幕才会显示图标最终正确的位置。

这是代码:

import React, {Component} from 'react';
import {View, Text, StyleSheet, Animated, Image, Dimensions, TouchableWithoutFeedback} from 'react-native';
import colors from '../config/colors';
import Icon from 'react-native-vector-icons/Ionicons';
import Orientation from 'react-native-orientation-locker';

const w = (Dimensions.get('window').width);
const h = (Dimensions.get('window').height);
const r = h / w;

if (r > 1.9) {
    mission_font_heading = 14;
    mission_font = 12;
    check_dimension = 14;
    name_font = 10;
} else {
    mission_font_heading = 12;
    mission_font = 10;
    check_dimension = 12;
    name_font = 8;
}

class how_to_play9_screen extends Component {
    constructor (props) {
        super(props);
        this.state = {
            test: 0, //changing this state "fixes" the component's position
        }
    }

    componentDidMount() {
        Orientation.lockToPortrait();
    }

    openMenu() {}

    showMission() {
        this.setState({test: 2}); //this changes the state
    }

    render() {
        return (
            <View>
                <Image
                    style={styles.backgroundImage}
                    source={require('../images/Background.png')}
                >
                </Image>
                <View style={{alignItems: 'center'}}>
                    <TouchableWithoutFeedback onPress={() => this.showMission()}>
                        <View style={styles.missionContainer}>
                            <Text style={styles.missionTitleText}>
                                MISSION TITLE
                            </Text>
                            <Text style={styles.text}>
                                (X VP)
                            </Text>
                            <View style={{flexDirection: 'row'}}>
                                <Image
                                    style={styles.checkBox}
                                    source={require('../images/Checkbox.jpg')}
                                />
                                <Text style={styles.missionReqText}>
                                    Mission Requirement 1
                                </Text>
                            </View>
                        </View>
                    </TouchableWithoutFeedback>
                </View>
                // below is the absolute positioned component
                <View
                    style={{
                        position: 'absolute',
                        top: 5,
                        right: 5,
                    }}
                >
                    <TouchableWithoutFeedback
                        onPress={() => this.openMenu()}
                    >
                        <Icon
                            name='ios-menu'
                            size={(Dimensions.get('window').width) * .08}
                            color={colors.JBDarkTeal}
                        />
                    </TouchableWithoutFeedback>
                </View>
            </View>
        );
    }
}

const styles = StyleSheet.create({
    backgroundImage: {
        width: (Dimensions.get('window').height) * .65,
        height: (Dimensions.get('window').height) * 1.3,
        position: 'absolute',
        left: 0,
        top: 0,
    },
    missionContainer:  {
        backgroundColor: colors.JBTealTrans,
        borderWidth: 2,
        borderColor: colors.JBTan,
        marginVertical: 10,
        paddingVertical: 3,
        paddingRight: 5,
        width: '80%',
    },
    missionTitleText: {
        fontSize: mission_font_heading,
        textAlign: 'center',
        color: colors.JBTan,
        marginVertical: 3,
        marginHorizontal: 5,
    },
    text: {
        fontSize: mission_font,
        textAlign: 'center',
        color: colors.JBTan,
        marginVertical: 3,
    },
    missionReqText: {
        fontSize: 12,
        color: colors.JBTan,
        marginVertical: 3,
        marginLeft: 5,
        marginRight: 5,
    },
    checkBox: {
        width: check_dimension,
        height: check_dimension,
        marginVertical: 3,
        marginLeft: 5,
    },
})

export default how_to_play9_screen;

我希望图标和任何其他绝对定位的组件在屏幕打开时直接到达它们的最终位置。

编辑:我还应该提到以前的屏幕将方向锁定为横向,而此屏幕将其锁定回纵向。我发现如果我从另一个已经是纵向的屏幕加载这个屏幕,那么这个屏幕会正确渲染,所以它似乎不喜欢我改变方向。

标签: javascriptreact-nativepositionstateabsolute

解决方案


位置不是问题,问题是<Icon />尝试使用数字 instad Dimensionscalc 的大小,或者使这个 calc oncomponentDidMountrender


推荐阅读