E 'possibile Centro contenuti in un UIScrollView come foto di Apple App?
-
19-09-2019 - |
Domanda
Ho lottato con questo problema per qualche tempo e sembra che ci sia una risposta chiara. Per favore fatemi sapere se qualcuno ha capito questo.
Voglio visualizzare una foto in un UIScrollView
che è al centro dello schermo (l'immagine può essere in orientamento verticale o orizzontale).
Voglio essere in grado di zoom e pan l'immagine solo fino al bordo dell'immagine come nella foto app.
Ho provato alterare il contentInset
nel metodo viewDidEndZooming
e quella sorta di fa il trucco, ma ci sono diversi difetti.
Inoltre ho provato a fare il imageView
la stessa dimensione del scrollView
e centrare l'immagine lì. Il problema è che quando si esegue lo zoom, è possibile scorrere l'intero imageView
e parte dell'immagine può scorrere fuori la vista.
Ho trovato un post simile qui e dato il massimo soluzione, ma è stata trovata alcuna vera risposta:
Soluzione 3
Ecco la soluzione migliore che potrei fornire per questo problema. Il trucco è quello di regolare costantemente telaio della ImageView. Trovo che questo funziona molto meglio di regolare costantemente i contentInsets o contentOffSets. Ho dovuto aggiungere un po 'di codice aggiuntivo per accogliere entrambe le immagini ritratto e paesaggio.
Se qualcuno può trovare un modo migliore per farlo, mi piacerebbe sentirlo.
Ecco il codice:
- (void) scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale {
CGSize screenSize = [[self view] bounds].size;
if (myScrollView.zoomScale <= initialZoom +0.01) //This resolves a problem with the code not working correctly when zooming all the way out.
{
imageView.frame = [[self view] bounds];
[myScrollView setZoomScale:myScrollView.zoomScale +0.01];
}
if (myScrollView.zoomScale > initialZoom)
{
if (CGImageGetWidth(temporaryImage.CGImage) > CGImageGetHeight(temporaryImage.CGImage)) //If the image is wider than tall, do the following...
{
if (screenSize.height >= CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is greater than the zoomed height of the image do the following...
{
imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), 368);
}
if (screenSize.height < CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the height of the screen is less than the zoomed height of the image do the following...
{
imageView.frame = CGRectMake(0, 0, 320*(myScrollView.zoomScale), CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale]);
}
}
if (CGImageGetWidth(temporaryImage.CGImage) < CGImageGetHeight(temporaryImage.CGImage)) //If the image is taller than wide, do the following...
{
CGFloat portraitHeight;
if (CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale] < 368)
{ portraitHeight = 368;}
else {portraitHeight = CGImageGetHeight(temporaryImage.CGImage) * [myScrollView zoomScale];}
if (screenSize.width >= CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is greater than the zoomed width of the image do the following...
{
imageView.frame = CGRectMake(0, 0, 320, portraitHeight);
}
if (screenSize.width < CGImageGetWidth (temporaryImage.CGImage) * [myScrollView zoomScale]) //If the width of the screen is less than the zoomed width of the image do the following...
{
imageView.frame = CGRectMake(0, 0, CGImageGetWidth(temporaryImage.CGImage) * [myScrollView zoomScale], portraitHeight);
}
}
[myScrollView setZoomScale:myScrollView.zoomScale -0.01];
}
Ecco come calcolo la scala di zoom minimo nel metodo viewDidLoad.
CGSize photoSize = [temporaryImage size];
CGSize screenSize = [[self view] bounds].size;
CGFloat widthRatio = screenSize.width / photoSize.width;
CGFloat heightRatio = screenSize.height / photoSize.height;
initialZoom = (widthRatio > heightRatio) ? heightRatio : widthRatio;
[myScrollView setMinimumZoomScale:initialZoom];
[myScrollView setZoomScale:initialZoom];
[myScrollView setMaximumZoomScale:3.0];
Altri suggerimenti
Un modo elegante per centrare il contenuto di UISCrollView
è questo.
Aggiungi un osservatore alla contentSize della tua UIScrollView
, quindi questo metodo sarà chiamato ogni volta che il cambiamento contenuto ...
[myScrollView addObserver:delegate
forKeyPath:@"contentSize"
options:(NSKeyValueObservingOptionNew)
context:NULL];
Ora sul vostro metodo di osservatore:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
// Correct Object Class.
UIScrollView *pointer = object;
// Calculate Center.
CGFloat topCorrect = ([pointer bounds].size.height - [pointer viewWithTag:100].bounds.size.height * [pointer zoomScale]) / 2.0 ;
topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
topCorrect = topCorrect - ( pointer.frame.origin.y - imageGallery.frame.origin.y );
// Apply Correct Center.
pointer.center = CGPointMake(pointer.center.x,
pointer.center.y + topCorrect ); }
-
Si dovrebbe cambiare il
[pointer viewWithTag:100]
. Sostituire con il tuo visualizzare il contenutoUIView
.- cambia anche
imageGallery
indicando le dimensioni della finestra.
- cambia anche
Questo correggerà il centro del everytime contenuti sua cambio formato.
Nota: L'unico modo in cui questo contenuto non fare funziona molto bene è con funzionalità zoom standard del UIScrollView
.
Questo codice dovrebbe funzionare sulla maggior parte delle versioni di iOS (ed è stato testato per funzionare su 3.1 verso l'alto).
E 'basato sul codice di Apple WWDC per l'applicazione PhotoScroll.
Aggiungere il seguente per la vostra sottoclasse di UIScrollView, e sostituire tileContainerView con la vista contenente l'immagine o piastrelle:
- (void)layoutSubviews {
[super layoutSubviews];
// center the image as it becomes smaller than the size of the screen
CGSize boundsSize = self.bounds.size;
CGRect frameToCenter = tileContainerView.frame;
// center horizontally
if (frameToCenter.size.width < boundsSize.width)
frameToCenter.origin.x = (boundsSize.width - frameToCenter.size.width) / 2;
else
frameToCenter.origin.x = 0;
// center vertically
if (frameToCenter.size.height < boundsSize.height)
frameToCenter.origin.y = (boundsSize.height - frameToCenter.size.height) / 2;
else
frameToCenter.origin.y = 0;
tileContainerView.frame = frameToCenter;
}