iPhone UIWebView larghezza non rientra dopo lo zoom operazione + UIInterfaceOrientation cambiamento

StackOverflow https://stackoverflow.com/questions/2890673

Domanda

ho creato un ossa nude iPhone app con un UIWebView (Bilancia pagina per adattarla = YES, shouldAutorotateToInterfaceOrientation = YES) e caricato una pagina web, ad esempio, https://stackoverflow.com/

La rotazione al dispositivo indica che UIWebView è auto-ridimensionata in base alla larghezza. Buona.

non corretto : zoom nella pagina e zoom out. Ora ruotando il dispositivo spettacoli UIWebView in larghezza strano in uno dell'orientamento (se u l'immagine in orizzontale, la larghezza verticale è strano, viceversa). Questo comportamento è stato risolto solo quando si passa a un'altra pagina.

Corretto : Caricare lo stesso URL in Mobile Safari. Rotazione opere e le crisi larghezza indipendentemente l'esercizio zoom.

Questo è un bug UIWebView (probabilmente non)? O c'è qualcosa che deve essere fatto per rendere le cose "solo lavoro" come in Safari Mobile?

È stato utile?

Soluzione

Ho trovato qualcosa che ha funzionato per me. Il problema è che quando UIWebView cambia il suo contenuto orientamento web sono zoommed per adattarsi con finestra. Ma parametro zoomscale di ScrollView visualizzazione secondaria non viene aggiornato correttamente (e non vengono aggiornati minimumZoomScale né maximumZoomScale

Poi abbiamo bisogno di farlo manualmente in willRotateToInterfaceOrientation:

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    CGFloat ratioAspect = webview.bounds.size.width/webview.bounds.size.height;
    switch (toInterfaceOrientation) {
        case UIInterfaceOrientationPortraitUpsideDown:
        case UIInterfaceOrientationPortrait:
            // Going to Portrait mode
            for (UIScrollView *scroll in [webview subviews]) { //we get the scrollview 
                // Make sure it really is a scroll view and reset the zoom scale.
                if ([scroll respondsToSelector:@selector(setZoomScale:)]){
                    scroll.minimumZoomScale = scroll.minimumZoomScale/ratioAspect;
                    scroll.maximumZoomScale = scroll.maximumZoomScale/ratioAspect;
                    [scroll setZoomScale:(scroll.zoomScale/ratioAspect) animated:YES];
                }
            }
            break;
        default:
            // Going to Landscape mode
            for (UIScrollView *scroll in [webview subviews]) { //we get the scrollview 
                // Make sure it really is a scroll view and reset the zoom scale.
                if ([scroll respondsToSelector:@selector(setZoomScale:)]){
                    scroll.minimumZoomScale = scroll.minimumZoomScale *ratioAspect;
                    scroll.maximumZoomScale = scroll.maximumZoomScale *ratioAspect;
                    [scroll setZoomScale:(scroll.zoomScale*ratioAspect) animated:YES];
                }
            }
            break;
    }
}

Spero che questo aiuti!

Altri suggerimenti

Ho provato la soluzione dal M Penadés e questo sembra funzionare per me.

L'unico problema che sto vivendo è che quando si esegue questa operazione su un 3Gs la rotazione è, purtroppo, non molto liscia.

Sono quindi ora utilizzando un approccio diverso:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {

[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];

CGFloat scale = browserWebView.contentScaleFactor;
NSString *javaStuff = [NSString stringWithFormat:@"document.body.style.zoom = %f;", scale];
[browserWebView stringByEvaluatingJavaScriptFromString:javaStuff];

}

Con i migliori saluti,
Ralph

- (UIScrollView *)findScrollViewInsideView:(UIView *)view
{
    for(UIView *subview in view.subviews){
        if([subview isKindOfClass:[UIScrollView class]]){
            return (UIScrollView *)subview;
        }

        UIScrollView *foundScrollView = [self findScrollViewInsideView:subview];
        if (foundScrollView){
            return foundScrollView;
        }
    }

    return nil;
}

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation
{
    switch (self.interfaceOrientation){
        case UIInterfaceOrientationLandscapeLeft:
        case UIInterfaceOrientationLandscapeRight:
        {
            UIScrollView *webViewScrollView = ([self.webView respondsToSelector:@selector(scrollView)])
                ? self.webView.scrollView
                : [self findScrollViewInsideView:self.webView];

            [webViewScrollView setZoomScale:1.01f animated:YES];
        }
            break;

        default:
            break;
    }
}

provare questo codice, cambia insignificante livello di zoom (1.01) per consentire aumenta la dimensione del UIWebView contenuti in modalità orizzontale

findScrollViewInsideView: metodo aggiunto al supporto iOS4

Sto inviando questo perché ho anche affrontato lo stesso problema e qui sto seguendo il M Penades Approach.M Penades s' Answer wok buono solo per caso se l'utente non Skew (pinch Out) WebView quindi ruotare il dispositivo e ripetere questo processo .poi contenuto Dimensioni di UIWebView si riduce gradualmente. in modo che era il problema è venuto in M Penades risposta. così ho fissato tale questione troppo e il mio codice è il seguente.

1) Per questo ho impostato il gesto Pinch in modo che quando l'utente Skew UIWebView potrebbe controllare la dimensione in scala di UIWebView.         // One Questo prega di importare il protocollo UIGestureRecognizerDelegate in 'file h'

     //call below method in ViewDidLoad Method for setting the Pinch gesture 

- (void)setPinchgesture
{
     UIPinchGestureRecognizer * pinchgesture = [[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(didPinchWebView:)];

    [pinchgesture setDelegate:self];

    [htmlWebView addGestureRecognizer:pinchgesture];
    [pinchgesture release];
   // here htmlWebView is WebView user zoomingIn/Out 

}
   //Allow The allow simultaneous recognition

  - (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer   *)otherGestureRecognizer
  {
     return YES;
  }

SI Tornando è garantito per consentire il riconoscimento simultaneo. restituendo NO non è garantita per evitare che il riconoscimento simultaneo, in qualità di delegato del l'altro gesto può restituire YES

 -(void)didPinchWebView:(UIPinchGestureRecognizer*)gestsure
   {
   //check if the Scaled Fator is same is normal scaling factor the allow set Flag True.
    if(gestsure.scale<=1.0)
    {
    isPinchOut = TRUE;

    }
    else// otherwise Set false
    {
    isPinchOut = FALSE;
   }
  NSLog(@"Hello Pinch %f",gestsure.scale);
}

Se l'utente Hase Pinch In / Out Il Web View in quel caso solo set che Zoom Factor.     SO che WebView può registrare la relativa contentSize come cambiato Oreintaion.

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation   duration:(NSTimeInterval)duration {

   //Allow the Execution of below code when user has Skewed the UIWebView and Adjust the Content Size of UiwebView.

  if(isPinchOut){
  CGFloat ratioAspect = htmlWebView.bounds.size.width/htmlWebView.bounds.size.height;
  switch (toInterfaceOrientation) {
    case UIInterfaceOrientationPortraitUpsideDown:
    case UIInterfaceOrientationPortrait:
        // Going to Portrait mode
        for (UIScrollView *scroll in [htmlWebView subviews]) { //we get the scrollview
            // Make sure it really is a scroll view and reset the zoom scale.
            if ([scroll respondsToSelector:@selector(setZoomScale:)]){
                scroll.minimumZoomScale = scroll.minimumZoomScale/ratioAspect;
                scroll.maximumZoomScale = scroll.maximumZoomScale/ratioAspect;
                [scroll setZoomScale:(scroll.zoomScale/ratioAspect) animated:YES];
            }
        }
        break;

    default:
        // Going to Landscape mode
        for (UIScrollView *scroll in [htmlWebView subviews]) { //we get the scrollview
            // Make sure it really is a scroll view and reset the zoom scale.
            if ([scroll respondsToSelector:@selector(setZoomScale:)]){
                scroll.minimumZoomScale = scroll.minimumZoomScale *ratioAspect;
                scroll.maximumZoomScale = scroll.maximumZoomScale *ratioAspect;
                [scroll setZoomScale:(scroll.zoomScale*ratioAspect) animated:YES];
            }
        }
        break;
     }
  }

}

Questo funziona perfettamente per l'utente, anche inclinare l'UIWebView.

Ho una soluzione a questo problema, ma devo dire che non sono un grande fan di esso. E le grandi opere, ma la soluzione effettivamente provoca un altro problema. Ho una correzione per il problema secondario, ma ci vuole un po 'di sforzo.

Basta tenere a mente che, poiché OS3.2 o iOS4 (non sono sicuro che) visualizzazione secondaria diretta di UIWebView è ora UIScrollView invece di UIScroller, in modo che possiamo fare molto di più con esso. Inoltre, dal momento che l'accesso a subviews di una visione, non è un'azione privata, né sta usando una visualizzazione secondaria che viene colato come una vista documentato possiamo fare molto con l'UIWebView senza infrangere le regole.

In primo luogo abbiamo bisogno di ottenere l'UIScrollView dal UIWebView:

UIScrollView *sview = [[webView subviews] objectAtIndex:0];

Ora abbiamo bisogno di cambiare il delegato di questa ScrollView in modo che possiamo ignorare le chiamate delegato ScrollView (che potrebbe in realtà essere la causa di un bug secondaria a seguito di questa soluzione, che ho intenzione di condividere in un attimo):

sview.delegate = self;

Ora, se si prova a questo punto, lo zoom è rotto. Abbiamo bisogno di implementare un metodo UIScrollViewDelegate per risolvere il problema. aggiungere:

- (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView {
    UIView *webBrowserView = [[scrollView subviews] objectAtIndex:10];
    return webBrowserView;
}

webBrowserView è in realtà un UIWebBrowserView, ma che non è una classe documentata, quindi stiamo solo andando a trattarlo come un UIView.

Ora eseguire la vostra applicazione, zoom in e zoom out poi la pagina web. Ruota, e dovrebbe essere visualizzato correttamente.

Questo provoca una piuttosto grande bug, che è forse peggiore di quella originale.

Se si esegue lo zoom in e poi ruotare, si perderanno scorrimento capacità, ma la vostra vista verrà ingrandita ancora. Ecco la correzione Per completare il tutto.

In primo luogo, abbiamo bisogno di tenere traccia di alcuni numeri, e hanno una bandiera definito:

Ho questi definiti nel mio file h:

BOOL updateZoomData;
float zoomData; //this holds the scale at which we are zoomed in, scrollView.zoomScale
CGPoint zoomOffset; //this holds the scrollView.contentOffset
CGSize zoomContentSize; //this holds the scrollView.contentSize

E 'possibile pensare che si può semplicemente prendere questi numeri da UIScrollView, ma quando ne avete bisogno, si sono cambiati, quindi abbiamo bisogno di loro conservati altrove.

Abbiamo bisogno di utilizzare un altro metodo delegato:

- (void)scrollViewDidZoom:(UIScrollView *)scrollView{
    if(updateZoomData){
        zoomData = scrollView.zoomScale;
        zoomOffset = scrollView.contentOffset;
        zoomContentSize = scrollView.contentSize;
    }
}

Ora si entra in una sensazione di disordine I.

Abbiamo bisogno di tenere traccia di rotazione, quindi avrai bisogno di aggiungere questo alla vostra viewDidLoad, loadview, o qualsiasi metodo utilizzato per registrare le notifiche:

[[NSNotificationCenter defaultCenter] addObserver:self 
            selector:@selector(webViewOrientationChanged:) 
            name:UIDeviceOrientationDidChangeNotification 
            object:nil];

e creare questo metodo:

- (void)webViewOrientationChanged:(NSNotification *)notification{
    updateZoomData = NO;
    [self performSelector:@selector(adjustWithZoomData) withObject:nil afterDelay:0.0];
}

Così ora ogni volta che si ruota webViewOrientationChange verrà chiamato. Il motivo performSelector viene ritardata per 0,0 secondi è perché vogliamo chiamare adjustWithZoomData sul prossimo runloop. Se si chiama direttamente, l'adjustWithZoomData regolerà per l'orientamento precedente.

Ecco il metodo adjustWithZoomData:

- (void)adjustWithZoomData{
    UIScrollView *sview = [[webView subviews] objectAtIndex:0];
    [sview setZoomScale:zoomData animated:YES];
    [sview setContentOffset:zoomOffset animated:YES]; 
    [sview setContentSize:zoomContentSize];
    updateZoomData = YES;
}

Ecco fatto! Ora, quando si ruota manterrà lo zoom, e più o meno di mantenere l'offset corretto. Se qualcuno vuole fare i calcoli su come ottenere l'esatto corretto compensare quindi andare per esso!

I stava cercando in questo me stesso e ha scoperto qualche informazione in più:

Problemi al cambio zoom:

  1. Safari spesso non si ridisegna correttamente (se non del tutto), anche se il livello di zoom è cambiato.
  2. Modifica delle forze di larghezza ridipingere.
  3. si potrebbe pensare width = device-width nel paesaggio userebbe 1024 ma sembra utilizzare 768 (screen.width accade troppo).

es. se la larghezza corrente è 1024 e si desidera ingrandire 1-1,5 nel paesaggio si potrebbe:

  • Modifica combinazione di larghezza e zoom per esempio la larghezza a 2048 e lo zoom a 0,75
  • larghezza cambiamento a 1023 (brutto aliasing?)
  • larghezza cambiamento a dire 1023, poi la prossima linea di fondo a 1024 (doppio riverniciare, ma almeno finestra viene ridipinto).

Quindi, a quanto pare io non ha utilizzato la soluzione da M Penadés alla fine (e dimenticato di aggiornare questo post! Sorry).

Quello che ho fatto è stato quello di ridimensionare l'intero documento (e cambiare il mio font-size per mantenere le cose proporzionale). Che a quanto pare risolto il problema.

Tuttavia, la mia UIWebView è solo per caricare il mio codice HTML e CSS dal file system iOS -. Se si sta costruendo un browser web di uso generale, questo trucco non può funzionare così

ViewController.m

- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration {
    switch (toInterfaceOrientation) {
        case UIInterfaceOrientationPortraitUpsideDown:
        case UIInterfaceOrientationPortrait:
            if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)) {
                [webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'ppad'"];
            } else {
                [webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'pphone'"];
            }
            break;
        default:
            if ((UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)) {
                [webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'lpad'"];
            } else {
                [webview stringByEvaluatingJavaScriptFromString:@"document.body.className = 'lphone'"];
            }
            break;
    }
}

E app.css

html>body.pphone { font-size:12px; width: 980px; }
html>body.lphone { font-size:18px; width: 1470px; }
html>body.ppad { font-size:12px; width: 768px; }
html>body.lpad { font-size:15.99999996px; width: 1024px; }

https://gist.github.com/d6589584944685909ae5

In rotazione, prova a porre la ScrollView zoomScale a 0. Vedere la mia risposta completa qui: non regolato al nuovo telaio dopo la rotazione

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top