Xamarin.iOS中用UIPopoverPresentationController实现旋转时Popover居中
在Xamarin.iOS中实现旋转时UIPopover保持屏幕居中
我懂你找了一堆资料但大多都是iOS8以前或者Swift/OC的内容,Xamarin.iOS的相关方案确实比较少,这就给你一步步讲清楚怎么用UIPopoverPresentationController实现旋转时让popover保持屏幕居中的需求:
核心思路
要让popover旋转时不跑偏,关键是禁用箭头方向(让popover摆脱源视图的位置限制),并利用WillReposition事件在旋转触发时实时重新计算居中位置。
完整实现代码
1. 初始化并配置Popover(在宿主ViewController的ViewDidLoad中)
首先确保你的弹出控制器设置为Popover模态样式,同时完成基础配置:
public override void ViewDidLoad() { base.ViewDidLoad(); // 替换成你自己的菜单控制器实例 _menuController = new YourMenuViewController(); // 设置模态样式为Popover _menuController.ModalPresentationStyle = UIModalPresentationStyle.Popover; var popoverPresenter = _menuController.PopoverPresentationController; if (popoverPresenter != null) { // 禁用箭头方向,这样popover可以自由放置在屏幕任意位置 popoverPresenter.PermittedArrowDirections = UIPopoverArrowDirection.None; // 绑定旋转重定位事件 popoverPresenter.WillReposition += OnPopoverWillReposition; // 随便设置一个源视图和源矩形(因为箭头禁用了,这里只是满足系统要求) popoverPresenter.SourceView = View; popoverPresenter.SourceRect = new CGRect(View.Bounds.Center.X, View.Bounds.Center.Y, 1, 1); } // 弹出菜单控制器 PresentViewController(_menuController, true, null); }
2. 实现旋转重定位事件
当设备旋转时,系统会触发WillReposition事件,我们在这里重新计算popover的居中frame:
private void OnPopoverWillReposition(object sender, UIPopoverRepositionEventArgs e) { var popoverPresenter = sender as UIPopoverPresentationController; if (popoverPresenter == null) return; // 获取旋转后的屏幕边界 var screenBounds = UIScreen.MainScreen.Bounds; // 这里替换成你popover的实际内容尺寸 var popoverContentSize = new CGSize(320, 480); // 计算居中位置的坐标 var centerX = screenBounds.GetMidX() - popoverContentSize.Width / 2; var centerY = screenBounds.GetMidY() - popoverContentSize.Height / 2; // 更新popover的位置 e.NewPopoverRect = new CGRect(centerX, centerY, popoverContentSize.Width, popoverContentSize.Height); }
3. 可选:适配旋转时的内容尺寸
如果你的popover内容需要根据横竖屏调整大小,可以在菜单控制器的ViewWillLayoutSubviews中设置:
// 在你的菜单控制器(YourMenuViewController)中 public override void ViewWillLayoutSubviews() { base.ViewWillLayoutSubviews(); // 根据当前屏幕方向调整内容尺寸 if (UIDevice.CurrentDevice.Orientation.IsLandscape) { PreferredContentSize = new CGSize(480, 320); // 横屏尺寸 } else { PreferredContentSize = new CGSize(320, 480); // 竖屏尺寸 } }
为什么这么做?
PermittedArrowDirections = UIPopoverArrowDirection.None:让popover不再依赖源视图的箭头指向,允许我们自由控制它的位置。WillReposition事件:这是系统在popover需要重定位时触发的回调,刚好可以用来在旋转时重新计算居中坐标。- 动态设置
PreferredContentSize:确保popover在横竖屏切换时内容尺寸适配,居中效果更自然。
这样设置后,不管设备怎么旋转,你的popover都会稳稳地保持在屏幕中心啦!
内容的提问来源于stack exchange,提问作者Joseph
相关产品推荐
相关产品推荐

