You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Expo屏幕方向锁定导致iOS打开模态框时崩溃问题求助

Expo iOS横屏锁定后打开模态框崩溃+initialOrientation不生效问题排查

问题描述

用Expo开发横版游戏时碰到两个棘手问题:

  1. 通过useEffect调用ScreenOrientation.lockAsync(LANDSCAPE)锁定横屏后,iOS设备打开模态框直接崩溃;
  2. 尝试在app.json的expo-screen-orientation插件里配置initialOrientation: "LANDSCAPE",但完全没效果。

最小复现代码

App.js

import * as ScreenOrientation from 'expo-screen-orientation';
import { Animated, Modal, ScrollView, StyleSheet, Text, TextInput, TouchableOpacity, View } from 'react-native';
import { useEffect, useState } from 'react';

export default function App() {
    useEffect(() => {
        async function changeScreenOrientation() {
            await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE);
        }

        changeScreenOrientation();
    }, []);
    const [modalVisible, setModalVisible] = useState(false);

    return (
        <View style={styles.container}>
            <TouchableOpacity style={styles.button} onPress={() => setModalVisible(true)}>
                <Text style={styles.textStyle}>Open</Text>
            </TouchableOpacity>
            <Modal animationType='slide' transparent={true} visible={modalVisible} onRequestClose={() => setModalVisible(false)}>
                <View style={styles.centeredView}>
                    <View style={styles.modalView}>
                        <TouchableOpacity style={styles.button} onPress={() => setModalVisible(false)}>
                            <Text style={styles.textStyle}>Close</Text>
                        </TouchableOpacity>
                    </View>
                </View>
            </Modal>
        </View>
    );
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: '#f0f0f0',
    },
    button: {
        borderRadius: 20,
        padding: 10,
        elevation: 2,
        marginTop: 15,
        backgroundColor: '#2196F3',
    },
    textStyle: {
        color: 'white',
        fontWeight: 'bold',
        textAlign: 'center',
    },
    centeredView: {
        flex: 1,
        justifyContent: 'center',
        alignItems: 'center',
        backgroundColor: 'rgba(0,0,0,0.5)',
    },
    modalView: {
        margin: 20,
        backgroundColor: 'white',
        borderRadius: 20,
        padding: 35,
        alignItems: 'center',
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.25,
        shadowRadius: 4,
        elevation: 5,
    },
});

app.json

{
    "expo": {
        "name": "Player",
        "slug": "Player",
        "version": "1.0.0",
        "orientation": "portrait",
        "icon": "./assets/icon.png",
        "userInterfaceStyle": "light",
        "splash": {
            "image": "./assets/splash.png",
            "resizeMode": "contain",
            "backgroundColor": "#ffffff"
        },
        "assetBundlePatterns": ["**/*"],
        "ios": {
            "supportsTablet": true,
            "requireFullScreen": true
        },
        "android": {
            "adaptiveIcon": {
                "foregroundImage": "./assets/adaptive-icon.png",
                "backgroundColor": "#ffffff"
            }
        },
        "web": {
            "favicon": "./assets/favicon.png"
        },
        "plugins": [
            [
                "expo-screen-orientation",
                {
                    "initialOrientation": "LANDSCAPE"
                }
            ]
        ]
    }
}

解决方案

1. iOS模态框崩溃修复

iOS上模态框默认会强制竖屏,和全局横屏锁冲突导致崩溃。解决办法是在模态框显示/隐藏时动态调整方向锁:

  • 打开模态框时临时解锁方向,允许系统自动适配
  • 关闭模态框后重新锁定横屏

修改后的核心代码:

// 新增两个回调函数
const handleModalShow = async () => {
  await ScreenOrientation.unlockAsync();
};

const handleModalDismiss = async () => {
  await ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE);
};

// 给Modal组件添加回调
<Modal 
  animationType='slide' 
  transparent={true} 
  visible={modalVisible} 
  onRequestClose={() => setModalVisible(false)}
  onShow={handleModalShow}
  onDismiss={handleModalDismiss}
>
  {/* 模态框内容不变 */}
</Modal>

2. initialOrientation配置不生效修复

你的app.json里根节点的"orientation": "portrait"和插件的initialOrientation冲突了,Expo优先取根节点配置。只需修改根节点的orientation为横屏即可:

{
  "expo": {
    // ...其他配置
    "orientation": "landscape", // 把portrait改成landscape
    // ...插件配置可保留或删除,根节点配置已足够
  }
}

注意事项

  • 修改app.json的orientation后,必须重新构建native项目(eas build或expo run:ios),热重载不会生效
  • Expo Go可能无法加载native层面的配置,建议用自定义开发客户端测试

内容的提问来源于stack exchange,提问作者Shep Sims

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.29 20:34:55