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

Xamarin Forms iOS16横竖屏切换失效及代码报错解决咨询

Xamarin Forms iOS 16横竖屏切换适配问题

开发环境:Visual Studio 2019 for Mac + Xcode 12.4
此前通过DependencyService实现的部分页面横竖屏切换在iOS 15及以下版本正常,但iOS 16中失效。原有参考代码如下:

AppDelegate.cs

public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, [Transient] UIWindow forWindow)
{
    if (App.IsAllowRotation)
    {
        return UIInterfaceOrientationMask.Landscape;
    }
    else
    {
        return UIInterfaceOrientationMask.Portrait;
    }
}

iOS端OrientationService

public class OrientationService : IOrientationHandler
{
    public void Landscape()
    {
        UIDevice.CurrentDevice.SetValueForKey(new NSNumber((int)UIInterfaceOrientation.LandscapeRight), new NSString("orientation"));
    }

    public void Portrait()
    {
        UIDevice.CurrentDevice.SetValueForKey(new NSNumber((int)UIInterfaceOrientation.Portrait), new NSString("orientation"));
    }
}

尝试适配iOS 16更新Service代码后,出现SetNeedsUpdateOfSupportedInterfaceOrientations()、RequestGeometryUpdate、UIWindowSceneGeometryPreferencesIOS相关报错,需解决以下问题:

  • 需要引入哪些命名空间?
  • iOS 16下Service及AppDelegate需做哪些修改?

所需命名空间

在iOS项目的OrientationService文件顶部添加以下命名空间:

using UIKit;
using Foundation;
using System.Linq; // 用于场景查询的LINQ方法

UIWindowSceneGeometryPreferencesIOS、RequestGeometryUpdate等API均属于UIKit命名空间,同时需确保Xamarin.iOS版本已更新至支持iOS 16的版本,否则会出现API不存在的报错。

iOS 16下OrientationService修改

修复代码错误并优化窗口场景获取逻辑,修改后的代码如下:

public class OrientationService : IOrientationHandler
{
    public void Landscape()
    {
        if (UIDevice.CurrentDevice.CheckSystemVersion(16, 0))
        {
            // 获取当前活跃的前台WindowScene
            var windowScene = UIApplication.SharedApplication.ConnectedScenes
                .OfType<UIWindowScene>()
                .FirstOrDefault(scene => scene.ActivationState == UISceneActivationState.ForegroundActive);
            
            if (windowScene != null)
            {
                var rootVC = windowScene.Windows.FirstOrDefault()?.RootViewController;
                if (rootVC != null)
                {
                    App.IsAllowRotation = true;
                    rootVC.SetNeedsUpdateOfSupportedInterfaceOrientations();
                    
                    // 请求横屏模式更新
                    var preferences = new UIWindowSceneGeometryPreferencesIOS(UIInterfaceOrientationMask.Landscape);
                    windowScene.RequestGeometryUpdate(preferences, error =>
                    {
                        if (error != null)
                        {
                            Console.WriteLine($"横屏切换错误: {error.LocalizedDescription}");
                        }
                    });
                }
            }
        }
        else
        {
            App.IsAllowRotation = true;
            UIDevice.CurrentDevice.SetValueForKey(new NSNumber((int)UIInterfaceOrientation.LandscapeRight), new NSString("orientation"));
        }
    }

    public void Portrait()
    {
        if (UIDevice.CurrentDevice.CheckSystemVersion(16, 0))
        {
            var windowScene = UIApplication.SharedApplication.ConnectedScenes
                .OfType<UIWindowScene>()
                .FirstOrDefault(scene => scene.ActivationState == UISceneActivationState.ForegroundActive);
            
            if (windowScene != null)
            {
                var rootVC = windowScene.Windows.FirstOrDefault()?.RootViewController;
                if (rootVC != null)
                {
                    App.IsAllowRotation = false;
                    rootVC.SetNeedsUpdateOfSupportedInterfaceOrientations();
                    
                    // 请求竖屏模式更新
                    var preferences = new UIWindowSceneGeometryPreferencesIOS(UIInterfaceOrientationMask.Portrait);
                    windowScene.RequestGeometryUpdate(preferences, error =>
                    {
                        if (error != null)
                        {
                            Console.WriteLine($"竖屏切换错误: {error.LocalizedDescription}");
                        }
                    });
                }
            }
        }
        else
        {
            App.IsAllowRotation = false;
            UIDevice.CurrentDevice.SetValueForKey(new NSNumber((int)UIInterfaceOrientation.Portrait), new NSString("orientation"));
        }
    }
}

关键调整:

  • 替换KeyWindow为windowScene.Windows.FirstOrDefault(),符合iOS 13+窗口管理规范
  • 优先获取活跃前台场景,避免操作后台无效场景
  • 修正Landscape方法中误传竖屏掩码的错误
  • 切换前更新全局App.IsAllowRotation标记,确保AppDelegate的方向判断逻辑同步生效

AppDelegate适配修改

iOS 16需添加针对UIWindowScene的重载方法,确保系统能正确获取支持的方向:

// 兼容iOS 15及以下版本的原有重载
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, [Transient] UIWindow forWindow)
{
    return GetSupportedOrientations();
}

// 适配iOS 13+的Scene模式重载
public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations(UIApplication application, UIWindowScene forWindowScene)
{
    return GetSupportedOrientations();
}

// 提取公共判断逻辑,减少代码冗余
private UIInterfaceOrientationMask GetSupportedOrientations()
{
    return App.IsAllowRotation ? UIInterfaceOrientationMask.Landscape : UIInterfaceOrientationMask.Portrait;
}

关键修改:

  • 添加UIWindowScene参数的重载方法,iOS 13+系统会优先调用此方法
  • 公共方法统一处理方向判断,保证多版本逻辑一致性

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 18:01:27