2010-09-05 17 views
6

Desidero aggiornare manualmente lodi un UIScrollView durante le modifiche di rotazione. La vista a scorrimento riempie lo schermo e ha una larghezza flessibile e un'altezza flessibile.contentOffset di UIScrollView durante la rotazione

Attualmente sto cercando di aggiornare il contentOffset in willRotateToInterfaceOrientation, in questo modo:

- (void) willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    [Utils logPoint:myScrollView.contentOffset tag:@"initial"]; 
    myScrollView.contentOffset = CGPointMake(modifiedX, modifiedY); 
    [Utils logPoint:myScrollView.contentOffset tag:@"modified"]; 
} 

-(void) didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation { 
    [Utils logPoint:myScrollView.contentOffset tag:@"final"]; 
} 

Tuttavia, il valore finale non è il valore modificato, e sembra un pò ad essere influenzato da esso, ma non è evidente per me come.

Questi sono alcuni dei risultati che ottengo:

initial: (146.000000;-266.000000) 
modified: (81.000000;-108.000000) 
final: (59.000000;-0.000000) 

initial: (146.000000;-266.000000) 
modified: (500.000000;500.000000) 
final: (59.000000;500.000000) 

initial: (146.000000;-266.000000) 
modified: (-500.000000;-500.000000) 
final: (-0.000000;-0.000000) 

Come posso aggiornare il contentOffset di una vista di scorrimento durante un cambio di rotazione?

+1

Hai provato cambiando la contentOffset in 'willAnimateRotationToInterfaceOrientation' invece? A questo punto dovrebbe essere presente un blocco di animazione, forse il risultato è diverso. – Pascal

+0

@Pascal Sì, e funziona perfettamente. Comunque mi piacerebbe sapere perché non si comporta come previsto se lo cambio in willRotateToInterfaceOrientation. – hpique

+0

La mia ipotesi sarebbe che il frame del genitore cambi solo ** dopo ** 'willRotateToInterfaceOrientation', quindi si imposta un contentOffset diverso, ma quello viene cambiato immediatamente di nuovo perché anche il frame della superview cambia solo in quel momento. Per il sistema operativo è come se aveste cambiato il frame qualche tempo prima, non rispetto alla rotazione in sospeso. – Pascal

risposta

12

Conversione mio commento ad una risposta :)

Prova a cambiare contentOffset dall'interno willAnimateRotationToInterfaceOrientation:duration: invece. A questo punto dovrebbe essere presente un blocco di animazione e il sistema operativo considera le modifiche a contentOffset come appartenenti alle modifiche causate dalla rotazione.

Se si modifica contentOffset in precedenza, sembra che il sistema non rispetti queste modifiche come appartenenti alla rotazione e applichi comunque il ridimensionamento della rotazione, questa volta a partire dalle nuove dimensioni.

+0

Ha funzionato come un fascino, aggiungendo frammenti di codice per aiutare gli altri. – Shardul

+1

questo metodo è deprecato. Prova a usare 'viewWillTransitionToSize' o' willTransitionToTraitCollection' – Gerald

4

Gli snippet seguenti sono il trucco quando l'impaginazione è abilitata su UIScrollView e lo spostamento della pagina deve essere mantenuto.

dichiarare una proprietà che calcolerà la posizione di currentPage prima della rotazione, e impostare su -1 in viewDidLoad

@property (assign, nonatomic) NSInteger lastPageBeforeRotate; 

Poi override del metodo willRotateToInterfaceOrientation:toInterfaceOrientation:duration e assegnare valore calcolato ad esso.

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
    int pageWidth = self.scrollView.contentSize.width/self.images.count; 
    int scrolledX = self.scrollView.contentOffset.x; 
    self.lastPageBeforeRotate = 0; 

    if (pageWidth > 0) { 
     self.lastPageBeforeRotate = scrolledX/pageWidth; 
    } 

    [self showBackButton:NO]; 
} 

Allora facciamo in modo che prima di effettuare la rotazione, abbiamo impostato contenuto del nostro ScrollView compensato correttamente, in modo da concentrare al nostro lastPageBeforeRotate

- (void)willAnimateRotationToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration { 
     if (self.lastPageBeforeRotate != -1) { 
      self.scrollView.contentOffset = CGPointMake(self.scrollView.bounds.size.width * self.lastPageBeforeRotate, 0); 
      self.lastPageBeforeRotate = -1; 
     } 
} 
+0

Grazie mille! Questa è l'unica soluzione che ha funzionato per me :) –

3

risposta aggiornata per iOS 8+

Implementare viewWillTransitionToSize: withTransitionCoordinator: nel controller.

Esempio:

-(void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator { 
    NSUInteger visiblePage = (NSInteger) self.scrollView.contentOffset.x/self.scrollView.bounds.size.width; 

    [coordinator animateAlongsideTransition:^(id<UIViewControllerTransitionCoordinatorContext> _Nonnull context) { 
     self.scrollView.contentOffset = CGPointMake(visiblePage * self.scrollView.bounds.size.width, self.scrollView.contentOffset.y); 
    } completion:nil]; 
} 
+0

Grazie! È interessante notare che scrollView.bounds utilizza il nuovo/diverso valore all'interno della funzione animateAlongsideTransition. –

Problemi correlati