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
相关产品推荐
相关产品推荐

