iPhone UIWebView ancho no se ajusta el zoom después de la operación de cambio + UIInterfaceOrientation

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

Pregunta

I creó un esqueleto iPhone aplicación con un UIWebView (escalas página para ajustarse = SÍ, shouldAutorotateToInterfaceOrientation = SÍ) y se carga una página web, por ejemplo, https://stackoverflow.com/

Rotación de los espectáculos de dispositivo que UIWebView es auto-cambiar de tamaño para ajustarse al ancho. Buena.

incorrecta : Zoom en la página y alejar la imagen. Ahora girar el dispositivo shows UIWebView en una anchura extraño en una de la orientación (si u acercar paisaje, la anchura retrato es raro, viceversa). Este comportamiento se fija sólo cuando se desplaza a otra página.

correcta : Cargar la misma URL en Mobile Safari. Rotación de las obras y los ajustes de anchura sin tener en cuenta el ejercicio zoom.

Es esto un error UIWebView (probablemente no)? O hay algo que hay que hacer más cosas para hacer "trabajo justo" como en Safari Mobile?

¿Fue útil?

Solución

He encontrado algo que funcionó para mí. El problema es que cuando cambia su contenido UIWebView orientación web están zoommed para encajar con el visor. Pero parámetro zoomscale de subvista ScrollView no se actualiza correctamente (ni se actualizan minimumZoomScale ni maximumZoomScale

A continuación, tenemos que hacerlo de forma manual en 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;
    }
}

Espero que esto ayude!

Otros consejos

He intentado la solución de H Penadés y esto parece que funciona para mí también.

El único problema que estoy experimentando es que cuando se ejecuta este en un 3Gs la rotación es, por desgracia, no muy suave.

Ahora estoy por lo tanto, el uso de un enfoque diferente:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {

[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];

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

}

Mejores Saludos, 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;
    }
}

probar este código, se cambia el nivel de zoom de forma insignificante (1,01) para permitir aumentar tamaño UIWebView contenido en modo horizontal

findScrollViewInsideView: método añade a apoyo iOS4

Estoy publicar esto porque yo también se han enfrentado el mismo problema y aquí estoy siguiendo el M Penades Approach.M Penades 's woks respuesta Bueno sólo para el caso si el usuario no Skew (pellizca) la Webview luego gire el dispositivo y repita este proceso .then Tamaño contenido de UIWebView consigue reducir de forma gradual. por lo que era el problema se produjo en respuesta M Penades. por lo que he fijado esa cuestión también y mi código es como sigue.

1) para esta fijo el gesto de pellizco de modo que cuando el Usuario Skew El UIWebView podría comprobar el tamaño a escala de UIWebView. // Una Esto favor importar el Protocolo UIGestureRecognizerDelegate en 'archivo .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 Volviendo está garantizada para permitir el reconocimiento simultáneo. Volviendo NO no está garantizada para impedir el reconocimiento simultáneo, como delegado del otro gesto puede devolver 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);
}

Si el usuario Hase Pinch / reducir la Web en ese caso acaba de establecer que el factor de zoom. De manera que pueda ajustar su WebView ContentSize como Changed 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;
     }
  }

}

Esto funciona perfectamente para sesgar el usuario incluso UIWebView.

Tengo una solución a este problema, pero tengo que decir que no soy un gran fan de ella. Funciona muy bien, pero la solución realmente causa otro problema. Tengo una solución para el problema secundario, pero se necesita un poco de esfuerzo.

Hemos de tener en cuenta que, dado OS3.2 o iOS4 (no estoy seguro) subvista directa de UIWebView es ahora UIScrollView en lugar de UIScroller, por lo que podemos hacer mucho más con ella. Además, dado que el acceso a subvistas de una vista no es una acción privada, ni utiliza una subvista que se coló como una vista documentado que podemos hacer mucho con el UIWebView sin romper las reglas.

En primer lugar tenemos que conseguir el UIScrollView del UIWebView:

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

Ahora tenemos que cambiar el delegado de este ScrollView para que podamos anular llamadas delegado ScrollView (que en realidad puede ser la causa de un error secundaria como resultado de esta solución, que voy a compartir en un momento):

sview.delegate = self;

Ahora, si lo intenta en este punto, el zoom se rompe. Debemos poner en práctica un método UIScrollViewDelegate para solucionarlo. añadir:

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

webBrowserView es en realidad un UIWebBrowserView, pero eso no es una clase documentado, por lo que sólo vamos a tratarla como una UIView.

Ahora ejecute su aplicación, acercar y alejar la imagen a continuación, la página web. Girar, y debería aparecer correctamente.

Esto hace causa un error bastante grande, que es tal vez peor que el original.

Si se acerca y luego gira, que va a perder la capacidad de desplazamiento, pero su vista se ampliarán aún. Aquí está la solución Para completar todo el asunto.

En primer lugar, tenemos que hacer un seguimiento de algunos números, y tienen una bandera definido:

He éstas se definen en el archivo de mi 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

Usted puede pensar que sólo puede agarrar estos números de UIScrollView, pero cuando los necesite, se han cambiado, por lo que necesitamos de ellos almacenados en otro lugar.

Tenemos que utilizar otro método delegado:

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

Ahora se pone en una sensación de desorden que.

Es necesario realizar un seguimiento de la rotación, por lo que tendrá que añadir esto a su viewDidLoad, loadView, o lo que sea el método que utilice para registrar notificaciones:

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

y crear este método:

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

Así que ahora cada vez que gira webViewOrientationChange se llamará. La razón performSelector se retrasa durante 0,0 segundos es porque queremos llamar adjustWithZoomData en la siguiente runloop. Si usted lo llama directamente, el adjustWithZoomData se ajustará a la orientación anterior.

Este es el método adjustWithZoomData:

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

Eso es todo! Ahora cuando gira que mantendrá el zoom, y más o menos mantener el desplazamiento correcto. Si alguien quiere hacer los cálculos sobre cómo conseguir la compensación exacta correcta, entonces ir a por ello!

Me estaba investigando esto mismo y descubrió algo más de información:

Problemas al cambiar el zoom:

  1. Safari menudo no se vuelve a dibujar correctamente (en su caso) a pesar de que el nivel de zoom cambia.
  2. Cambio de las fuerzas de anchura un repintado.
  3. se podría pensar width = dispositivo de ancho en el paisaje usaría 1024, pero parece que utilizar 768 (screen.width sucede también).

por ejemplo. si el ancho actual es 1024 y que desea acercar entre 1 y 1,5 en el paisaje que podía:

  • cambio combinación de anchura y zoom, por ejemplo, anchura a 2048 y zoom a 0,75
  • cambio de anchura a 1023 (feo aliasing?)
  • anchura de cambio decirlo 1023, entonces la próxima vuelta a la línea 1024 (doble repintado, pero al menos se pintaron ventana).

Así que al parecer no hice uso de la solución de M Penadés, al final (y se olvidó de actualizar este post! Lo siento).

Lo que hice fue cambiar el tamaño de todo el documento (y cambiar de tamaño de fuente para mantener las cosas proporcional). Que aparentemente ha solucionado el problema.

Sin embargo, mi UIWebView es sólo para cargar mi propio código HTML y CSS desde el sistema de archivos IOS -. Si usted está construyendo un navegador web de propósito general, este truco puede no funcionar tan bien

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;
    }
}

Y 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; }

Gist en https://gist.github.com/d6589584944685909ae5

En la rotación, intente configurar el ScrollView zoomScale a 0. Véase mi respuesta completa aquí: no está ajustado a nueva trama después de la rotación

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top