Search code examples
iosxamarinxamarin.iospopover

Xamarin.iOS Popovers on Rotate


I've seen lots and lots of posts about handling rotation for iOS popovers, but the majority of them target < iOS8 and/or Swift/ObjC. How can I do this with UIPopoverPresentationController and Xamarin.iOS? I need to keep it in the center of the screen.

  public override void ViewDidLoad()
  {
     ...

     _menuController.PopoverPresentationController.PermittedArrowDirections = 0;
     _menuController.PopoverPresentationController.WillReposition += OnWillReposition;
  }

  private void OnMenuSelected(object sender, EventArgs eventArgs)
  {
     InitializePopover();

     PresentViewController(_menuController, true, null);
  }

  private void OnWillReposition(object sender, UIPopoverPresentationControllerRepositionEventArgs args)
  {
     InitializePopover();
  }

  private void InitializePopover()
  {
     _menuController.PopoverPresentationController.SourceRect = GetCenterRect();
     _menuController.PopoverPresentationController.SourceView = View;
  }

  private CGRect GetCenterRect()
  {
     var midX = View.Bounds.GetMidX();
     var midY = View.Bounds.GetMidY();
     return new CGRect(midX, midY, 0, 0);
  }

OnWillReposition is called on rotation, but setting the SourceRect and SourceView doesn't appear to take effect. When I rotate again, I can see during debug that those properties have the old values.

Popular links I've seen so far:

Other thoughts:

  • Can I reposition in ViewDidLayoutSubviews? How?

  • Using a UIBarButtonItem isn't really an option, but maybe an invisible one?

  • Should I dismiss and present again? Seems hacky and I was getting exceptions...

  • Should I give up and simply set another view over everything else?


Solution

  • I figured it out just before posting. My problem was that I wasn't setting PermittedArrowDirections each time. Vent: Who thought that was a good idea? Anyway, after making that part of initialization, I simply call that in ViewDidLayoutSubviews, as below:

      public override void ViewDidLayoutSubviews()
      {
         base.ViewDidLayoutSubviews();
    
         InitializePopover();
      }
    
      private void InitializePopover()
      {
         _menuController.PopoverPresentationController.PermittedArrowDirections = 0;
         _menuController.PopoverPresentationController.SourceRect = GetCenterRect();
         _menuController.PopoverPresentationController.SourceView = View;
      }
    

    So I don't use the UIPopoverPresentationController.WillReposition event at all. I hope this helps somebody -- I wouldn't want my worst enemy to go through all that frustration.