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

Xamarin.Forms iOS16强制屏幕旋转失效问题求助

解决iOS 16+ Xamarin.Forms登录页强制竖屏无效问题

问题根源

iOS 16起,Apple废弃了AppDelegate中GetSupportedInterfaceOrientations的全局调用逻辑,转而要求在ViewController层级控制屏幕方向,同时UIWindowScene的方向更新API需要更严谨的调用方式。你的代码中AppDelegate的方法不再被触发,且SetPortrait方法存在两处关键问题:

  • 获取windowScene的方式不够可靠(直接取第一个ConnectedScene可能不是当前活跃场景)
  • 未正确关联当前页面的ViewController来触发方向更新

修复步骤

1. 移除AppDelegate中的方向判断代码

直接删除GetSupportedInterfaceOrientations方法,后续方向控制由自定义Renderer处理。

2. 为LoginPage创建自定义PageRenderer

在iOS项目中添加LoginPage的Renderer,强制该页面仅支持竖屏:

[assembly: ExportRenderer(typeof(LoginPage), typeof(LoginPageRenderer))]
namespace YourAppName.iOS.Renderers
{
    public class LoginPageRenderer : PageRenderer
    {
        public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations()
        {
            return UIInterfaceOrientationMask.Portrait;
        }

        public override bool ShouldAutorotate()
        {
            return false;
        }
    }
}

这个Renderer会在LoginPage显示时,覆盖ViewController的方向支持逻辑,确保iOS16能正确识别该页面的竖屏要求。

3. 修正SetPortrait方法的实现

更新InterfaceOrientationService.cs中的代码,确保正确获取当前活跃的windowScene,并触发方向更新:

public void SetPortrait()
{
    if (UIDevice.CurrentDevice.CheckSystemVersion(16, 0))
    {
        // 获取当前活跃的UIWindowScene(更可靠的方式)
        var windowScene = UIApplication.SharedApplication.ConnectedScenes
            .OfType<UIWindowScene>()
            .FirstOrDefault(scene => scene.ActivationState == UISceneActivationState.ForegroundActive);
        
        if (windowScene != null)
        {
            // 获取当前显示的最顶层ViewController
            var currentVC = UIApplication.SharedApplication.KeyWindow?.RootViewController;
            while (currentVC?.PresentedViewController != null)
            {
                currentVC = currentVC.PresentedViewController;
            }

            if (currentVC != null)
            {
                currentVC.SetNeedsUpdateOfSupportedInterfaceOrientations();
                var preferences = new UIWindowSceneGeometryPreferencesIOS(UIInterfaceOrientationMask.Portrait);
                windowScene.RequestGeometryUpdate(preferences, error =>
                {
                    if (error != null)
                    {
                        Console.WriteLine($"方向更新失败: {error.LocalizedDescription}");
                    }
                });
            }
        }
    }
    else
    {
        // iOS16以下保留原有逻辑
        UIDevice.CurrentDevice.SetValueForKey(NSNumber.FromInt32((int)UIInterfaceOrientation.Portrait), new NSString("orientation"));
        UIApplication.SharedApplication.StatusBarOrientation = UIInterfaceOrientation.Portrait;
    }
}

关键改进点:

  • 通过ForegroundActive状态获取当前活跃的windowScene,避免取到后台场景
  • 遍历获取最顶层的PresentedViewController,确保是当前显示的页面
  • 添加错误回调,方便排查更新失败的原因

4. 检查Info.plist的方向设置

确保Info.plist中允许所有方向(后续由代码动态控制):

  • 在Info.plist中,找到UISupportedInterfaceOrientations,添加以下项:
    • Portrait (bottom home button)
    • Landscape left
    • Landscape right
  • 同时UISupportedInterfaceOrientations~ipad也做相同设置(如果支持iPad)

额外注意事项

  • 确保LoginPage的OnAppearing方法中调用SetPortrait时,页面已经完成渲染(可延迟100ms调用,避免页面未加载完成导致的问题):
protected override async void OnAppearing()
{
    base.OnAppearing();
    await Task.Delay(100);
    DependencyService.Get<IInterfaceOrientationService>().SetPortrait();
}
  • 如果使用NavigationPage,确保其他页面的Renderer正确传递方向支持逻辑(如果需要横屏)

内容的提问来源于stack exchange,提问作者Lisa Maria

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.15 10:51:24