2014-06-30 15 views
17

Zauważyłem w projekcie, że umieszczenie popover nad prawym elementem przycisku wydaje się być z prawej strony nie tak z jakiegoś powodu. Próbowałem zamiast tego użyć UIButton dla niestandardowego widoku, a następnie wyświetlając popover z tego przycisku, ale popover zdaje się ignorować showFromRect, jeśli faktycznie dostarczę mu wartość "wyśrodkowaną".UIPopover presentFromBarButton poza centrum

Off-center popover

Kod za to jest dość prosta:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    UIBarButtonItem *button = [[UIBarButtonItem alloc] initWithImage:[UIImage imageNamed:@"share"] style:UIBarButtonItemStylePlain target:self action:@selector(shareTap:)]; 

    self.navigationItem.rightBarButtonItem = button; 
} 

- (void)shareTap:(UIBarButtonItem *)button { 
    self.popover = [[UIPopoverController alloc] initWithContentViewController:[[UIViewController alloc] init]]; 

    [self.popover presentPopoverFromBarButtonItem:button permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES]; 
} 

Teraz, jeśli przełączyć się za pomocą przycisku wewnętrznego, jak wspomniano, widzę podobne zachowanie (zmiana koloru notatka więc obraz wyświetlany).

using internal button

Kod do tego jest jeszcze dość prosta:

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    UIButton *innerButton = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, 22, 22)]; 
    [innerButton setImage:[UIImage imageNamed:@"share"] forState:UIControlStateNormal]; 
    [innerButton addTarget:self action:@selector(shareTap:) forControlEvents:UIControlEventTouchUpInside]; 

    self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:innerButton];; 
} 

- (void)shareTap:(UIButton *)button { 
    self.popover = [[UIPopoverController alloc] initWithContentViewController:[[UIViewController alloc] init]]; 

// CGRect bottomCenter = CGRectMake(button.frame.size.width/2, button.frame.size.height, 1, 1); 
    CGRect bottomCenter = CGRectMake(2, button.frame.size.height, 1, 1); 

    [self.popover presentPopoverFromRect:bottomCenter inView:button permittedArrowDirections:UIPopoverArrowDirectionUp animated:YES]; 
} 

Uwaga tutaj, że zamiast korzystać z rzeczywistą, Użyłem dowolną wartość, 2. Jeżeli używam 1 lub 0, popover zostanie wyrównany do lewej. Wszystko większe niż jeden jest ponownie wyrównane do prawej.

left-aligned

Szukałem około trochę patrząc na podobne pytanie, ale nie wydaje się znaleźć kogoś z tym samym problemem. Każdy pomysł na temat tego, co to powoduje lub jak tego uniknąć, byłby bardzo doceniony. Jedyne, co mogłem zgadnąć, to fakt, że ze względu na bliskość krawędzi, Apple robi kilka voodoo pozycjonujących, by zmusić go do tego, by tego chciał. Problem polega na tym, że przycisk w prawym górnym rogu wydaje się być całkiem standardową pozycją rozwijaną.

Edytuj: Potwierdziłem, że to samo zachowanie występuje po długim naciśnięciu ikony "Nowa wiadomość" w macierzystej aplikacji Poczta.

Edycja 2: Udało mi się potwierdzić w Apple, że to jest problem. W jednej z nowszych wersji (nie pamiętam, który, jak sądzę, jeden z 9), zrobili to, więc możesz ustawić to ręcznie. Domyślne zachowanie jest nadal nieprawidłowe Wierzę (nie próbowałem tego przez jakiś czas), ale możesz użyć metody offset CGRect, aby działała poprawnie, gdybyś był tak pochłonięty.

+0

Spróbuj UIBarButtonItem * Przycisk = [[UIBarButtonItem alloc] initWithBarButtonSystemItem: target UIBarButtonSystemItemAction: działanie samodzielne: @selector (ShareTap :)]; – Nishant

+1

Czy mógłbyś wytłumaczyć nieco więcej?Używanie elementu systemowego samemu nie naprawia rozmieszczenia przycisków, a w mojej edycji wspomniałem, że domyślne aplikacje również wystawiają problem (Mail), które prawdopodobnie używają ikon systemowych. – shortstuffsushi

Odpowiedz

-2

Wypróbuj ten niestandardowy kontroler Popover - WYPopoverController (https://github.com/nicolaschengdev/WYPopoverController), aby naprawić problem.

+2

Nie szukam biblioteki zastępczej dla przeglądarek, tylko próbuję zrozumieć zachowanie rodzimego kontrolera. I faktycznie, pierwszy zrzut ekranu kontrolera WY jest również poza centrum :(Mimo wszystko jednak. – shortstuffsushi

0

Oto jeden sposób: Zamiast używać UIBarButtonSystemItem, użyj UIBarButtonItem z niestandardowym widokiem. Po prostu przeciągnij UIButton do UINavigationBar, aby uzyskać UIBarButtonItem z osadzonym UIButton, który pojawia się jako niestandardowy widok UIBarButtonItem.

@IBAction func didTapActionButton(_ sender: Any) { 
    if let vc = self.storyboard?.instantiateViewController(withIdentifier: "myPopover") { 
     vc.modalPresentationStyle = .popover 
     guard let innerView = actionButton.customView else { 
      // Unexpected missing custom view 
      return 
     } 

     vc.popoverPresentationController?.sourceView = navigationController?.navigationBar 
     vc.popoverPresentationController?.sourceRect = innerView.frame 
     self.present(vc, animated: true, completion: nil) 
    } 
} 
+0

Myślę, że możesz zauważyć, że jest to poprawione post iOS 9. Wspomniałem na początku mojego posta, że ​​nawet UIButton nie działa, ale później (w edycji), którą Apple zaktualizował, abyś * mógł * poprawić pozycjonowanie za pomocą UIButton. – shortstuffsushi

+0

Miałem problem z przesunięciem strzałki popover, który opisałeś pierwotnie w projekcie na iOS 10, i to było poprawka dla mnie - myślę, że mówisz, że ta metoda nie zadziałałaby w systemie iOS 9, w którym błąd był obecny. Nie próbowałem tego. – stevex

0

Należy określić ramkę przycisku paska, z którego należy wyświetlić pop.

Poniższy kod przedstawia UIAlertController jako popover z przycisku paska.

@IBOutlet weak var playerRightBarButton: UIBarButtonItem! 

    extension UIBarButtonItem { 
     var frame: CGRect? { 
     guard let view = self.value(forKey: "view") as? UIView else { 
      return nil 
     } 
     return view.frame 
    } 
    } 

    let alert = UIAlertController(title: "", message: "Sample PopOver", 
    preferredStyle: .actionSheet) 
    if alert.responds(to: #selector(getter: popoverPresentationController)) { 
      alert.popoverPresentationController?.sourceView = self.view 
      alert.popoverPresentationController?.barButtonItem = playerRightBarButton 
      alert.popoverPresentationController?.permittedArrowDirections = .up 
      if let frame = playerRightBarButton.frame { 
       alert.popoverPresentationController?.sourceRect = frame 
      } 
     } 
     self.present(alert, animated: true, completion: nil) 
+0

Nie jestem do końca pewien, ale nie sądzę jest to związane z moim pytanie.Jak to odnosi się do umieszczania strzałki? Jakiego "frame" masz na myśli ustawienie? Czy mówisz o dodaniu tej metody rozszerzenia do klasy UIBarButtonItem? – shortstuffsushi

+0

Rozszerzenie daje ramkę barButton. możemy ustawić Ramka, z której musi zostać zaprezentowany popover, odpowiednio się do niej centralizuje. Podałem przykład alertController prezentujący jako popOver na iPada. – Swathi