2012-09-06 11 views
6

Voglio aiuto con il mio campione UIScrollView.salta allo zoom out con UIScrollView

Ho creato un semplice programma che scorre e ingrandisce il contenuto (UIImageView). Funziona bene, tranne che il contenuto scompare frequentemente in basso a destra quando provo lo zoom. Ma dal momento che ho impostato minimumZoomScale su 1.0f, non è in realtà lo zoom, solo il contenuto sta saltando fuori dalla vista. E quello che è ancora più strano è che non posso più scorrere dopo questo. Apparentemente la dimensione del contenuto è incasinata.

enter image description here

La configurazione che ho nel mio codice di esempio è come nella figura sottostante.

enter image description here

Quando ho controllato lo stato dopo (cercando) zoom out, ho trovato due cose sbagliate.

  • _scrollView.contentSize è 480x360, che non deve essere inferiore a 1000x1000
  • _scrollView.bounds saltato verso l'alto in qualche modo (vale a dire, _scrollView.bounds.origin.y è sempre 0)

di far fronte con i due elementi sopra, ho aggiunto il seguente codice nel mio UIScrollViewDelegate e ora funziona correttamente.

- (void)scrollViewWillBeginZooming:(UIScrollView *)scrollView withView:(UIView *)view 
{ 
    if(scrollView == _scrollView && view == _contentView) 
    { 
     // Setting ivars for scrollViewDidZoom 
     _contentOffsetBeforeZoom = _scrollView.contentOffset; 
     _scrollViewBoundsBeforeZoom = _scrollView.bounds; 
    } 
} 

- (void)scrollViewDidZoom:(UIScrollView *)scrollView 
{ 
    if(scrollView == _scrollView) 
    { 
     // If you zoom out, there are cases where ScrollView content size becomes smaller than original, 
     // even though minimum zoom scale = 1. In that case, it will mess with the contentOffset as well. 
     if(_scrollView.contentSize.width < CONTENT_WIDTH || _scrollView.contentSize.height < CONTENT_HEIGHT) 
     { 
      _scrollView.contentSize = CGSizeMake(CONTENT_WIDTH, CONTENT_HEIGHT); 
      _scrollView.contentOffset = _contentOffsetBeforeZoom; 
     } 

     // If you zoom out, there are cases where ScrollView bounds goes outsize of contentSize rectangle. 
     if(_scrollView.bounds.origin.x + _scrollView.bounds.size.width > _scrollView.contentSize.width || 
      _scrollView.bounds.origin.y + _scrollView.bounds.size.height > _scrollView.contentSize.height) 
     { 
      _scrollView.bounds = _scrollViewBoundsBeforeZoom; 
     }    
    } 
} 

Tuttavia, è necessario scendere a questo? Questa è una sequenza molto semplice, ed è difficile credere che Apple ci richieda di fare questo tipo di sforzo. Quindi, la mia scommessa è che mi manca qualcosa qui ...

Il seguente è il mio codice originale. Per favore aiutami a trovare quello che sto facendo male (o mi manca qualcosa)!

#define CONTENT_WIDTH 1000 
#define CONTENT_HEIGHT 1000 

    >>>> Snip >>>> 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view, typically from a nib. 

    _scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0, 0, 320, 460)]; 
    _scrollView.contentSize = CGSizeMake(CONTENT_WIDTH, CONTENT_HEIGHT); 
    _scrollView.backgroundColor = [UIColor blueColor]; 
    _scrollView.maximumZoomScale = 8.0f; 
    _scrollView.minimumZoomScale = 1.0f; 
    _scrollView.indicatorStyle = UIScrollViewIndicatorStyleWhite; 
    _scrollView.scrollEnabled = YES; 
    _scrollView.delegate = self; 
    [self.view addSubview:_scrollView]; 

    _contentView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"sample.jpg"]]; // sample.jpg is 480x360 
    CGPoint center = (CGPoint){_scrollView.contentSize.width/2, _scrollView.contentSize.height/2}; 
    _contentView.center = center; 
    [_scrollView addSubview:_contentView]; 

    _scrollView.contentOffset = (CGPoint) {center.x - _scrollView.bounds.size.width/2, center.y - _scrollView.bounds.size.height/2};   
} 

- (UIView *) viewForZoomingInScrollView:(UIScrollView *)scrollView 
{ 
    if(scrollView == _scrollView) 
    { 
     return _contentView; 
    } 
    return nil; 
} 
+1

Hai provato a impostare '_contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight; '? – Adam

+0

Grazie per il suggerimento. Ma no, non cambia la situazione ... – barley

+0

Posso chiederti perché il tuo 'contentSize' è 1000x1000? – tia

risposta

10

Ho creato un progetto di esempio rapido e ho riscontrato lo stesso problema descritto utilizzando il codice incollato. Non so esattamente quale sia il modo "corretto" per lo zoom in iOS, ma ho trovato il tutorial this che dice che è necessario eseguire il riavvio del contenuto dopo averlo ingrandito. Personalmente mi aspetto che venga automaticamente ricentrato in quanto è la vista che stai restituendo nel metodo delegato viewForZoomingInScrollView ma apparentemente no.

- (void)centerScrollViewContents { 
    CGSize boundsSize = _scrollView.bounds.size; 
    CGRect contentsFrame = _contentView.frame; 

    if (contentsFrame.size.width < boundsSize.width) { 
     contentsFrame.origin.x = (boundsSize.width - contentsFrame.size.width)/2.0f; 
    } else { 
     contentsFrame.origin.x = 0.0f; 
    } 

    if (contentsFrame.size.height < boundsSize.height) { 
     contentsFrame.origin.y = (boundsSize.height - contentsFrame.size.height)/2.0f; 
    } else { 
     contentsFrame.origin.y = 0.0f; 
    } 

    _contentView.frame = contentsFrame; 
} 

- (void)scrollViewDidZoom:(UIScrollView *)scrollView { 
    // The scroll view has zoomed, so we need to re-center the contents 
    [self centerScrollViewContents]; 
} 

Il codice di cui sopra non è scritto da me, ma viene semplicemente copiato dal tutorial. Penso che sia piuttosto semplice. Inoltre, il centraggio del contentView sembra essere molto più elegante, cambiando continuamente i limiti e le dimensioni del contenuto della scrollview, quindi provalo.

+0

Grazie per la risposta! Ha senso e ha funzionato bene. L'unica cosa nella tua risposta è che '_scrollView.frame' dovrebbe essere' _contentView.frame' nel mio contesto. Modificherò quella parte e selezionerò la mia risposta. – barley

0

Se qualcuno sta avendo un problema di rimbalzo quando si rimpicciolisce lo sfondo risultante da mostrare, provare a rimuovere rimbalzi (Zoom rimbalzi) in Interface Builder.

1

Sono stato in grado di risolvere questo problema utilizzando la risposta del delegato che ha regolato le tariffe dopo lo zoom ... ma poi mi sono ricordato che stavo usando il layout automatico e aggiungendo solo i vincoli per il centraggio orizzontale e verticale (oltre ai vincoli legando l'immagine a ciascun bordo della vista di scorrimento) risolto il problema senza utilizzare i metodi delegati.

+0

La domanda era dall'era del telaio e dei montanti, e felice di sapere che i vincoli risolvono elegantemente questo problema ora! – barley

Problemi correlati