8

Sto costruendo una GUI personalizzata su un'app universale per iPhone e iPad. Sull'iPad fa molto affidamento su "sideViews" per utility come la manipolazione dei contenuti, le informazioni dettagliate e simili (si pensi a un SplitView avanzato). Da un punto di vista visivo il nuovo UIPresentationController è perfetto per permettermi di presentare queste "sideview" (e non usare un dimmedView) e l'implementazione è stata semplice da costruire e mantenere, mentre si integra perfettamente con lo storyboard. Ma ho bisogno di essere in grado di manipolare il contenuto del PresentationViewController mentre ilViewController presentato è visibile. Quindi la mia domanda è: posso impostare userInteractionEnabled (o simile) sul presentViewViewer mentre presenta le sideViews?Posso rendere UIPresentationController avere userInteractionEnabled su PresentingViewController?

risposta

11

UIPresentationController inserisce la sua vista contenitore come una visualizzazione secondaria finestra sopra la vista presentazione, così eventuali tocchi di fuori del vista presentato rimangono intrappolati dalla vista contenitore e mai lo rendono alla vista di presentazione .

La correzione consiste nell'inserire una vista nella vista Contenitore che passa attraverso i tocchi alla vista di presentazione. È possibile utilizzare questa opzione come opzione di regolazione della luminosità o impostare backgroundColor su [UIColor clearColor] per una visualizzazione completamente trasparente. Impostare le visualizzazioni passthrough nel codice del controller di presentazione.

@interface IVPasserView : UIView 

@property (strong, nonatomic) NSArray* passthroughViews; 

@end 

@implementation IVPasserView 

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event 
{ 
    UIView* hit = [super hitTest:point withEvent:event]; 
    if (hit == self) 
     for (UIView* passthroughView in _passthroughViews) 
     { 
      hit = [passthroughView hitTest:[self convertPoint:point toView:passthroughView] 
           withEvent:event]; 
      if (hit) 
       break; 
     } 
    return hit; 
} 

@end 

Nota: mentre questo viola lo spirito di -[UIView hitTest:withEvent:] in quanto non restituisce una visualizzazione secondaria, questo è in realtà come il sistema standard di UIPopoverPresentationController gestisce. Se si imposta la proprietà passthroughViews, la vista Contenitore risponde a hitTest:withEvent: con una vista passthrough, anche se non sono superview/subview! Quindi è probabile che sopravviva alla prossima versione di iOS.

+0

Soluzione interessante. Ho assolutamente bisogno di fare un tentativo. – jollyCocoa

+0

Questa è una buona soluzione per esattamente il problema nel titolo della domanda. –

+0

Questo è stupendo. –

2

Ok, sembra che l'idea di UIPresentationController NON sia in grado di usarlo come SplitView avanzato (o almeno questa è la mia conclusione attuale). Sono riuscito a costruire una soluzione alternativa però. Se qualcuno trova un modo migliore di gestirlo, per favore fatemelo sapere nei commenti.

Quindi, quello che faccio è inserire la vista PresentingViewController nella containerViewContextsview (uguale alla gerarchia UIPresentationControllers containerView) all'indice 0. Ciò mi consente di gestire in modo trasparente touchEvents nella vista PresentingViewControllers. Ma rimuove la vista PresentingViewControllers dalla sua gerarchia di vista originale, quindi ho bisogno di spostarlo di nuovo quando la presentazione viene chiusa. Significa rimettere la vista alla vista di parentViewController se presente, o la finestra dell'app, se presentandoViewController è il rootViewController dell'app (potrebbero esserci anche altri scenari, ma per ora lo farà).

Questo è tutto fatto in animateTransition in UIViewControllerAnimatedTransitioning.

Ecco il pezzo di codice:

UIView.animateWithDuration(transitionDuration(transitionContext), 
     delay: 0.0, 
     usingSpringWithDamping: 1.0, 
     initialSpringVelocity: 0.5, 
     options: UIViewAnimationOptions.BeginFromCurrentState|UIViewAnimationOptions.AllowUserInteraction, 
     animations: {() -> Void in 
      animatingView.frame = finalFrame 
     }) { (finished:Bool) -> Void in 
      if !self.isPresentation { 
       if let parentViewController = backgroundVC.parentViewController { 
        parentViewController.view.addSubview(backgroundVC.view) 
       } 
       else if let window = (UIApplication.sharedApplication().delegate as! AppDelegate).window { 
        window.addSubview(backgroundVC.view) 
       } 
       fromView.removeFromSuperview() 
      } 
      else { 
       containerView.insertSubview(backgroundVC.view, atIndex: 0) 
      } 
      transitionContext.completeTransition(true) 
    } 
+1

Hai ragione che i controller di presentazione non sono adatti per creare viste divise personalizzate. Per questo, visualizzare il contenimento del controller è probabilmente una scelta migliore. –

1

La presentazione modale non è adatta alla situazione. È meglio implementare lo scenario con il controller di visualizzazione contenitore personalizzato e sovrascrivere il metodo showDetailViewController:sender: per gestire la presentazione di ulteriori controller di visualizzazione. Ad esempio, puoi adattare questo metodo per mostrare modal di controller vista su iPhone e a destra su iPad.

Ecco un estratto da Apple Documentation:

Presentando Versus Mostrando un View Controller

La classe UIViewController offre due modi per visualizzare un controller di vista :

Lo showViewController: mittente: e showDetailViewController: mittente: i metodi offrono il modo più flessibile e flessibile per visualizzare i controller della vista . Questi metodi consentono al controller della vista di presentazione di decidere come gestire la presentazione. Ad esempio, un controller di vista contenitore potrebbe incorporare il controller di visualizzazione come figlio anziché presentandolo in modo modale. Il comportamento predefinito presenta il controller della vista modally. Il metodo presentViewController: animated: completion: mostra sempre il controller della vista in modo modale. Il controller della vista che chiama questo metodo potrebbe non gestire in definitiva la presentazione ma la presentazione è sempre modale. Questo metodo adatta lo stile di presentazione per ambienti orizzontalmente compatti. Il showViewController: mittente: e showDetailViewController: mittente: metodi sono il modo preferito per avviare le presentazioni. Una vista del controller può chiamarli senza sapere nulla del resto della gerarchia del controller di visualizzazione o della posizione del controller di visualizzazione corrente in tale gerarchia. Questi metodi semplificano anche il riutilizzo dei controller di vista in diverse parti della tua app senza scrivere i percorsi di codice condizionale .

+0

Hey Alexander! Grazie per la risposta, e mi scuso per la risposta tardiva. Questo sicuramente sembra una soluzione interessante. Vedrò se risolverà il mio problema e se così ti darò credito. Per ora in eccesso, per una buona idea. – jollyCocoa

Problemi correlati