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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 07:53:23