UIPopover presentFromBarButton вне центра
Я заметил в проекте, что позиционирование popover над элементом правой кнопки панели кажется по праву по какой-то причине. Я попробовал вместо этого использовать UIButton для пользовательского представления, а затем представляю popover из этой кнопки, но popover, кажется, игнорирует showFromRect, если я действительно предоставляю ему "центрированное" значение.
![Off-center popover]()
Этот код довольно прост:
- (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];
}
Теперь, если я переключусь на использование внутренней кнопки, как уже упоминалось, я вижу подобное поведение (изменение цвета заметки, так что изображение появляется).
![using internal button]()
Код для этого довольно простой:
- (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];
}
Обратите внимание, что вместо того, чтобы использовать фактический центр, я использовал произвольное значение. 2. Если я использую 1 или 0, popover становится выровненным по левому краю. Все, что больше одного, снова выровнено по правому краю.
![left-aligned]()
Я немного искал поиск аналогичного вопроса, но я не могу найти никого с той же проблемой. Любая идея вокруг того, что вызывает это и как ее избежать, будет весьма признательна. Единственное, на что я мог догадаться, - это то, что из-за своей близости к краю Apple делает некоторое позиционирование вуду, чтобы заставить его быть там, где они этого хотят. Проблема в том, что кнопка в правом верхнем углу выглядит как довольно стандартная выпадающая позиция.
Изменить: я подтвердил, что такое же поведение происходит при длительном нажатии на значок "Новое сообщение" в приложении родной почты.
Изменить 2: Я смог подтвердить Apple, что это проблема. В одной из последних версий (я не могу вспомнить, какой из них я думаю), они сделали это так, чтобы вы могли вручную установить это. Поведение по умолчанию все еще не так. Я верю (я не пробовал это некоторое время), но вы можете использовать метод смещения CGRect, чтобы заставить его работать правильно, если вы так наклонены.
Ответы
Ответ 1
Здесь один из способов сделать это: вместо использования UIBarButtonSystemItem
используйте UIBarButtonItem
с пользовательским представлением. Просто перетащите UIButton
в UINavigationBar
, чтобы получить UIBarButtonItem
со встроенным UIButton
, который отображается как UIBarButtonItem
customView.
@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)
}
}
Ответ 2
Вы должны указать рамку кнопки на панели, из которой должен отображаться поп.
В следующем коде представлен символ UIAlertController
в виде popover из панели.
@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)
Ответ 3
Попробуйте этот пользовательский контроллер Popover - WYPopoverController (https://github.com/nicolaschengdev/WYPopoverController), чтобы устранить проблему.