Xamarin iOS:从ContentPage跳转UIViewController后返回按钮失效问题
解决从ContentPage打开UIViewController后无法返回的问题
你的问题出在直接创建了一个全新的UIWindow并替换了应用的根控制器,这导致原来的ContentPage所在的视图控制器层级被完全隔离,所以PopViewController和DismissViewController都无法找到要返回的页面——新窗口的导航栈里只有ScanningPage,而且原来的页面根本不在这个新窗口的层级体系中。
下面是两种可行的解决方案,优先推荐第一种:
方案一:用PresentViewController打开(符合iOS视图层级规范)
这是最标准的方式,通过获取当前应用的顶级视图控制器,以模态方式打开你的ScanningPage,这样就能正常用Dismiss返回。
步骤1:在共享项目定义接口
public interface INativePageService { void OpenScanningPage(); }
步骤2:在iOS项目实现接口
[assembly: Dependency(typeof(NativePageService))] namespace YourAppNamespace.iOS { public class NativePageService : INativePageService { public void OpenScanningPage() { // 获取当前显示的顶级视图控制器 var currentVC = UIApplication.SharedApplication.KeyWindow.RootViewController; while (currentVC.PresentedViewController != null) { currentVC = currentVC.PresentedViewController; } // 创建你的扫描页面和导航控制器 var scanningPage = new ScanningPage(); var navController = new UINavigationController(scanningPage); // 以模态方式打开 currentVC.PresentViewController(navController, true, null); } } }
步骤3:在ScanningPage添加返回按钮
public override void ViewDidLoad() { base.ViewDidLoad(); // 添加导航栏返回按钮 var backBtn = new UIBarButtonItem("返回", UIBarButtonItemStyle.Plain, (s, e) => { // 现在Dismiss就能回到原来的ContentPage了 this.DismissViewController(true, null); }); this.NavigationItem.LeftBarButtonItem = backBtn; }
方案二:保留原窗口(特殊场景使用)
如果因为某些需求必须用新窗口,那需要保存原来的KeyWindow,关闭新窗口时恢复它:
打开新窗口时保存原窗口
// 保存原来的主窗口 var originalWindow = UIApplication.SharedApplication.KeyWindow; // 创建新窗口并设置根控制器 var newWindow = new UIWindow(UIScreen.MainScreen.Bounds); var scanningPage = new ScanningPage(); var navController = new UINavigationController(scanningPage); newWindow.RootViewController = navController; newWindow.MakeKeyAndVisible(); // 将原窗口传递给ScanningPage(可以用静态属性) ScanningPage.OriginalMainWindow = originalWindow;
在ScanningPage中恢复原窗口
public static UIWindow OriginalMainWindow { get; set; } public override void ViewDidLoad() { base.ViewDidLoad(); var backBtn = new UIBarButtonItem("返回", UIBarButtonItemStyle.Plain, (s, e) => { // 恢复原来的主窗口 OriginalMainWindow.MakeKeyAndVisible(); // 释放新窗口资源 this.View.Window.ResignKey(); this.View.Window.Dispose(); }); this.NavigationItem.LeftBarButtonItem = backBtn; }
为什么原来的方法不行?
你原来的代码直接创建了新的UIWindow并调用MakeKeyAndVisible(),这会把应用的主窗口替换成新窗口,原来的ContentPage所在的视图控制器层级被“覆盖”了——新窗口的导航栈里只有ScanningPage,所以PopViewController没有上一个页面可返回;而DismissViewController要求当前控制器是被模态Present出来的,你直接把它设为根控制器,自然无法触发Dismiss逻辑。
内容的提问来源于stack exchange,提问作者Mannu
相关产品推荐
相关产品推荐

