Xamarin Forms iOS页面强制特定屏幕方向适配问题(iOS16+)
iOS 16+ 下 Xamarin Forms 页面强制指定屏幕方向的可行方案
在Xamarin Forms应用中,部分页面需要根据内容切换横竖屏,Android端实现无问题,但iOS 16移除了旧的UIDevice.SetValueForKey设置方向的方法,原MessagingCenter方案失效。以下是适配iOS 16+的完整实现步骤:
1. 定义共享接口
在共享项目中创建屏幕方向服务接口:
namespace MyApp { public interface IScreenOrientationService { void ForcePortrait(); void ForceLandscape(); void ResetToDefault(); } }
2. iOS平台实现依赖服务
在iOS项目中实现该接口,适配iOS 16+的新API,同时兼容旧版本:
[assembly: Xamarin.Forms.Dependency(typeof(MyApp.iOS.ScreenOrientationService))] namespace MyApp.iOS { public class ScreenOrientationService : IScreenOrientationService { private UIInterfaceOrientationMask _defaultOrientationMask; public ScreenOrientationService() { // 保存应用默认支持的方向掩码 _defaultOrientationMask = UIApplication.SharedApplication.SupportedInterfaceOrientationsForWindow(UIApplication.SharedApplication.KeyWindow); } public void ForcePortrait() { UpdateOrientation(UIInterfaceOrientationMask.Portrait); } public void ForceLandscape() { // 根据需求选择LandscapeLeft/LandscapeRight或同时支持 UpdateOrientation(UIInterfaceOrientationMask.LandscapeLeft | UIInterfaceOrientationMask.LandscapeRight); } public void ResetToDefault() { UpdateOrientation(_defaultOrientationMask); } private void UpdateOrientation(UIInterfaceOrientationMask targetMask) { if (UIDevice.CurrentDevice.CheckSystemVersion(16, 0)) { // 获取当前活跃的窗口场景 var windowScene = UIApplication.SharedApplication.ConnectedScenes .OfType<UIWindowScene>() .FirstOrDefault(scene => scene.ActivationState == UISceneActivationState.ForegroundActive); if (windowScene != null) { // 更新根视图控制器支持的方向 var rootVC = UIApplication.SharedApplication.KeyWindow?.RootViewController; if (rootVC != null) { // 自定义根视图控制器的支持方向(需要子类化UINavigationController) if (rootVC is CustomNavigationController navVC) { navVC.TargetOrientationMask = targetMask; navVC.SetNeedsUpdateOfSupportedInterfaceOrientations(); } // 请求窗口场景更新几何布局 var preferences = new UIWindowSceneGeometryPreferencesIOS(targetMask); windowScene.RequestGeometryUpdate(preferences, error => { if (error != null) { Console.WriteLine($"Orientation update error: {error.LocalizedDescription}"); } }); } } } else { // iOS 16以下的旧实现 UIInterfaceOrientation targetOrientation = UIInterfaceOrientation.Portrait; if (targetMask.HasFlag(UIInterfaceOrientationMask.LandscapeLeft)) { targetOrientation = UIInterfaceOrientation.LandscapeLeft; } else if (targetMask.HasFlag(UIInterfaceOrientationMask.LandscapeRight)) { targetOrientation = UIInterfaceOrientation.LandscapeRight; } UIDevice.CurrentDevice.SetValueForKey(NSNumber.FromInt32((int)targetOrientation), new NSString("orientation")); } } } // 子类化导航控制器,动态返回支持的方向 public class CustomNavigationController : UINavigationController { public UIInterfaceOrientationMask TargetOrientationMask { get; set; } = UIInterfaceOrientationMask.AllButUpsideDown; public override UIInterfaceOrientationMask GetSupportedInterfaceOrientations() { return TargetOrientationMask; } } }
3. 配置iOS项目的根视图控制器
在AppDelegate中,将默认的导航控制器替换为自定义的CustomNavigationController:
[Register("AppDelegate")] public partial class AppDelegate : global::Xamarin.Forms.Platform.iOS.FormsApplicationDelegate { public override bool FinishedLaunching(UIApplication app, NSDictionary options) { global::Xamarin.Forms.Forms.Init(); LoadApplication(new App()); // 替换根视图控制器为自定义导航控制器 var rootVC = new CustomNavigationController(Window.RootViewController); Window.RootViewController = rootVC; return base.FinishedLaunching(app, options); } }
4. 在页面中调用方向控制
在需要指定方向的页面的OnAppearing和OnDisappearing方法中调用服务:
protected override void OnAppearing() { base.OnAppearing(); // 强制横屏 DependencyService.Get<IScreenOrientationService>().ForceLandscape(); } protected override void OnDisappearing() { base.OnDisappearing(); // 恢复默认方向 DependencyService.Get<IScreenOrientationService>().ResetToDefault(); }
5. 配置Info.plist
确保Info.plist中包含应用需要支持的所有屏幕方向,否则强制方向会失效:
<key>UISupportedInterfaceOrientations</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array> <key>UISupportedInterfaceOrientations~ipad</key> <array> <string>UIInterfaceOrientationPortrait</string> <string>UIInterfaceOrientationPortraitUpsideDown</string> <string>UIInterfaceOrientationLandscapeLeft</string> <string>UIInterfaceOrientationLandscapeRight</string> </array>
内容的提问来源于stack exchange,提问作者Riley Houston
相关产品推荐
相关产品推荐

