14

I'm using UIBarButtonItem. In my scenario I want to show a popover from every bar button when I double-click that bar button. So I use a UITapGesture from that UIBarButtonItem. But, the popover arrow always appear in the middle of all UIBarButtonItem.

I can't make the arrow appear in the middle of each bar button. My friend was telling me to set the arrow direction using point, but I don't know how to do that.

How can I set both the position and direction of the popover's arrow?

thomaux
  • 19,133
  • 10
  • 76
  • 103
R. Dewi
  • 4,141
  • 9
  • 41
  • 66

5 Answers5

23

Set the direction for the popover using:

[yourPopover setPopoverArrowDirection: UIPopoverArrowDirectionDown];

You can also use UIPopoverArrowDirectionUp, UIPopoverArrowDirectionLeft, and UIPopoverArrowDirectionRight, and UIPopoverArrowDirectionAny.

For Swift

yourPopover?.permittedArrowDirections = .up // or .down, .left, .right
shim
  • 9,289
  • 12
  • 69
  • 108
Sam Ritchie
  • 10,988
  • 4
  • 42
  • 53
  • I know about that direction, but I mean I want to change the position of the direction.. I use UIPopoverArrowDirectionUp, but I want the arrow position is in X = 50 and y = 100, can I do that?? – R. Dewi Dec 08 '10 at 06:05
  • 1
    I really obsessed over this a few months back... Unfortunately, you can't specify the position of the arrow, only the rectangle that the uiipopover presents from. – Sam Ritchie Dec 08 '10 at 06:06
  • Nope it doesn't haha, I was kind of hoping Stackoverflow knew the answer to this question aswell... I have a hacky idea on getting it to work...but will only try it once I've given up finding a 3rd party PopoverCOntroller or found a proper way to move the X location of the arrow... Will update my similar Stackoverflow Question if an answer is found... – David van Dugteren Mar 23 '11 at 06:51
  • 1
    @SamRitchie But you **can** specify the position of the arrow by defining the CGRect it points at as having a size of 0 by 0. – Maple Oct 24 '13 at 18:12
  • @R.Dewi The accepted answer is correct, change the direction to down. – Cmag Oct 19 '16 at 05:59
  • Thanks, you made my day – David Ansermot Jul 01 '20 at 13:41
15

I use method permittedArrowDirections = .Down, It's work for me. Swift example:

if let popoverPresentationController = shareViewController.popoverPresentationController {
    popoverPresentationController.permittedArrowDirections = .Down
    popoverPresentationController.delegate = self
    popoverPresentationController.sourceView = sender as! UIButton
    popoverPresentationController.sourceRect = CGRectMake(0, 0, sender.frame.size.width, sender.frame.size.height)
}
Evgeny Karev
  • 605
  • 6
  • 13
  • 2
    you can use `popController.popoverPresentationController?.sourceView = sender as? UIView ; popController.popoverPresentationController?.sourceRect = sender.bounds` – Cmag Oct 19 '16 at 05:56
  • 2
    You can change `popoverPresentationController.sourceRect = CGRectMake(0, 0, sender.frame.size.width, sender.frame.size.height)` by `popoverPresentationController.sourceRect = sender.bounds` – CedricSoubrie Mar 22 '18 at 15:28
2
class MyViewController: UIViewController, UIPopoverPresentationControllerDelegate {

    @objc func expandClicked(sender: UIButton!) {
        let vc = UIViewController()
        vc.view.backgroundColor = .white
        display(viewcontroller: vc, size: CGSize(width: 150, height: 40), sender: sender)
    }

    func display(viewcontroller: UIViewController, size: CGSize, sender: UIView) {
        let controller = viewcontroller
        controller.modalPresentationStyle = .popover
        controller.popoverPresentationController?.delegate = self
        controller.preferredContentSize = size
        let presentationController = controller.popoverPresentationController!
        presentationController.sourceView = sender
        presentationController.sourceRect = sender.bounds
        presentationController.backgroundColor = .white
        let buttonPosition = CGPoint(x: sender.bounds.minX, y: sender.bounds.maxY)
        let p = sender.convert(buttonPosition, to: transactionTableView)
        if (transactionTableView.bounds.maxY - p.y) > 70 {
            presentationController.permittedArrowDirections = .up
        } else {
            presentationController.permittedArrowDirections = .down
        }
        self.present(controller, animated: true)
   }

   public func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
       return UIModalPresentationStyle.none 
   }
}
  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 21 '22 at 00:14
0

If you are using an IBAction method, you can use (id)sender as its parameter. (i.e. the calling button) Then you can set the popover's attachment rectangle to the frame of the button. The arrow will do its best to attach along the side of this frame in an appropriate spot. See UIPopoverController Class Reference.

-(IBAction)sortButtonPressed:(id)sender {
  // Set up your popover class, this varies per your implementation
  MyPopoverClass *iPop = [[MyPopoverClass alloc] initWithNibName:@"MyPopover" bundle:nil];
  UIPopoverController *popover = [[UIPopoverController alloc] initWithContentViewController:iPop];

  // Grab the button info from the input parameter
  UIButton *button = (UIButton *)sender;
  CGRect buttonRectangle = button.frame;

  // Set the arrow direction
  UIPopoverDirection dir = UIPopoverArrowDirectionAny; // Or Up, Down, etc.

  // Put it all together
  [popover presentPopoverFromRect:buttonRectangle inView:mySubView permittedArrowDirections:dir animated:YES];

  [popover release]
  [iPop release];
}

You can also hardcode that CGRect by hand if necessary. Shrinking the width/height of the rectangle will allow you to more tightly control the arrow's position.

Maple
  • 741
  • 13
  • 28
0

You can set the direction of the arrow in Storyboard Segue's attribute inspector. For example, I set the arrow direction to down only in the following screenshot: enter image description here

Linh Dao
  • 1,305
  • 1
  • 19
  • 31