iOS 8-UIPopoverPresentationController popover
ios8 (5)
Estoy buscando una manera efectiva de reubicar una ventana emergente usando el nuevo controlador de representación uipopover. He presentado exitosamente el popover, y ahora quiero moverlo sin descartar y presentar nuevamente. Estoy teniendo problemas para usar la función:
(void)popoverPresentationController:(UIPopoverPresentationController *)popoverPresentationController
willRepositionPopoverToRect:(inout CGRect *)rect
inView:(inout UIView **)view
Sé que es temprano en el juego, pero si alguien tiene un ejemplo de cómo hacerlo de manera eficiente, le agradecería que lo compartiera conmigo. Gracias por adelantado.
Aquí hay un ejemplo de cómo actualizar el popover:
- (void)popoverPresentationController:(UIPopoverPresentationController *)popoverPresentationController willRepositionPopoverToRect:(inout CGRect *)rect inView:(inout UIView **)view {
*rect = CGRectMake((CGRectGetWidth((*view).bounds)-2)*0.5f,(CGRectGetHeight((*view).bounds)-2)*0.5f, 2, 2);
También he usado este método para garantizar que la ventana emergente se haya movido a la ubicación correcta después de moverla, configurando las vistas * rect y * en el original SourceRect y SourceView.
Como nota adicional, no creo que se llame a este método cuando la fuente de la ventana emergente se establece mediante un elemento del botón de barra.
Desafortunadamente, esta solución pirata es la única solución que he encontrado:
[vc.popoverPresentationController setSourceRect:newSourceRect];
[vc setPreferredContentSize:CGRectInset(vc.view.frame, -0.01, 0.0).size];
Esto cambia temporalmente el tamaño del contenido de la vista presentada, lo que hace que la ventana emergente y la flecha se reposicionen. El cambio temporal en el tamaño no es visible.
Parece que este es un problema que Apple necesita arreglar: cambiar las propiedades sourceView
o sourceRect
de UIPopoverPresentationController
no hace nada cuando ya presenta una ventana emergente (sin esta solución).
¡Espero que esto funcione para usted también!
Estoy publicando esto porque no tengo suficientes puntos para votar o comentar. :) La respuesta de @ turbs funcionó perfectamente para mí. Debería ser la respuesta aceptada.
Ajuste * correcto al correcto que necesita en el método de delegado:
(void)popoverPresentationController:(UIPopoverPresentationController *)popoverPresentationController
willRepositionPopoverToRect:(inout CGRect *)rect
inView:(inout UIView **)view
Tuve suerte al usar containerView?.setNeedsLayout()
y containerView?.layoutIfNeeded()
después de cambiar el sourceRect
del popoverPresentationController
, así:
func movePopoverTo(_ newRect: CGRect) {
let popover = self.presentedViewController as? MyPopoverViewController {
popover.popoverPresentationController?.sourceRect = newRect
popover.popoverPresentationController?.containerView?.setNeedsLayout()
popover.popoverPresentationController?.containerView?.layoutIfNeeded()
}
}
E incluso para que una ventana emergente siga una celda tableView sin tener que cambiar nada:
class MyTableViewController: UITableViewController {
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "MyPopoverSegue" {
guard let controller = segue.destination as? MyPopoverViewController else { fatalError("Expected destination controller to be a ''MyPopoverViewController''!") }
guard let popoverPresentationController = controller.popoverPresentationController else { fatalError("No popoverPresentationController!") }
guard let rowIndexPath = sender as? IndexPath else { fatalError("Expected sender to be an ''IndexPath''!") }
guard myData.count > rowIndexPath.row else { fatalError("Index (/(rowIndexPath.row)) Out Of Bounds for array (count: /(myData.count))!") }
if self.presentedViewController is MyPopoverViewController {
self.presentedViewController?.dismiss(animated: false)
}
popoverPresentationController.sourceView = self.tableView
popoverPresentationController.sourceRect = self.tableView.rectForRow(at: rowIndexPath)
popoverPresentationController.passthroughViews = [self.tableView]
controller.configure(myData[rowIndexPath.row])
}
super.prepare(for: segue, sender: sender)
}
}
// MARK: - UIScrollViewDelegate
extension MyTableViewController {
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
if let popover = self.presentedViewController as? MyPopoverViewController {
popover.popoverPresentationController?.containerView?.setNeedsLayout()
popover.popoverPresentationController?.containerView?.layoutIfNeeded()
}
}
}
Utilicé el mismo método mencionado en otra respuesta por @Rowan_Jones, sin embargo, no quería que el tamaño de la ventana emergente cambiara realmente. Incluso por fracciones de un punto. Me di cuenta de que puede establecer el valor de contenido de contenido preferredContentSize
varias veces, pero visualmente su tamaño solo cambiará para coincidir con el último valor.
[vc.popoverPresentationController setSourceRect:newSourceRect];
CGSize finalDesiredSize = CGSizeMake(320, 480);
CGSize tempSize = CGSizeMake(finalDesiredSize.width, finalDesiredSize.height + 1);
[vc setPreferredContentSize:tempSize];
[vc setPreferredContentSize:finalDesiredSize];
Por lo tanto, incluso si finalDesiredSize
es el mismo que el preferredContentSize
esto hará que la finalDesiredSize
se actualice, aunque su tamaño no cambie realmente.