ios - UIPopover presentFromBarButton fuera del centro
uibarbuttonitem uipopovercontroller (2)
He notado en un proyecto que el posicionamiento de una ventana emergente sobre un elemento del botón de la barra derecha parece estar desviado hacia la derecha por alguna razón. En su lugar, he intentado usar un UIButton para la vista personalizada y luego presentar la ventana emergente desde ese botón, pero la ventana emergente parece ignorar el showFromRect si realmente le proporciono el valor ''centrado''.
El código detrás de esto es bastante simple:
- (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];
}
Ahora, si cambio al uso del botón interno, como se mencionó, veo un comportamiento similar (observe el cambio de color para que aparezca la imagen).
El código para esto es bastante simple:
- (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];
}
Tenga en cuenta que en lugar de usar el centro real, he usado el valor arbitrario, 2. Si uso 1 o 0, la ventana emergente se alinea a la izquierda. Cualquier cosa mayor que uno se alinea a la derecha nuevamente.
Busqué un poco buscando una pregunta similar, pero parece que no puedo encontrar a nadie con el mismo problema. Cualquier idea sobre qué causa esto o cómo evitarlo sería muy apreciada. Lo único que he podido adivinar es que debido a su proximidad con el borde, Apple hace un poco de vudú de posicionamiento para obligarlo a estar donde lo quieren. El problema es que el botón de la esquina superior derecha parece una posición desplegable bastante estándar.
Editar: He confirmado que este mismo comportamiento ocurre al presionar el ícono "Nuevo mensaje" en la aplicación de correo nativa.
Edición 2: pude confirmar con Apple que esto es un problema. En una de las versiones más recientes (no recuerdo cuál, una de las 9 creo), lo hicieron para que pueda configurar esto manualmente. Creo que el comportamiento predeterminado sigue siendo incorrecto (no lo he intentado durante un tiempo), pero puede utilizar el método de desplazamiento CGRect para que funcione correctamente, si así lo desea.
Aquí hay una forma de hacer esto: en lugar de usar un UIBarButtonSystemItem
, use un UIBarButtonItem
con una vista personalizada. Simplemente arrastre un UIButton
a la UINavigationBar
para obtener un UIBarButtonItem
con un UIButton
incrustado, que se muestra como UIBarButtonItem
del 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)
}
}
Debe especificar el marco del botón de barra desde el que se debe presentar la ventana emergente.
El siguiente código presenta un UIAlertController
como una UIAlertController
desde un botón de barra.
@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)