iPhone UIWebView largeur ne correspond pas après un zoom changement d'opération + UIInterfaceOrientation

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

Question

Je créé une application iPhone os nus avec une UIWebView (échelles à la page Fit = OUI, shouldAutorotateToInterfaceOrientation = YES) et chargé d'une page Web, par exemple https://stackoverflow.com/

rotation du dispositif montre que UIWebView est redimensionnée automatiquement à la largeur. Bon.

incorrect : Zoom sur la page et effectuer un zoom arrière. Maintenant, le dispositif de rotation montre UIWebView dans une largeur bizarre dans l'une de l'orientation (si u faire un zoom dans le paysage, la largeur de portrait est bizarre, vice versa). Ce comportement est fixé uniquement lorsque vous naviguez vers une autre page.

Correct : Chargez le même URL dans Safari Mobile. La rotation des œuvres et les ajustements largeur quel que soit l'exercice de zoom.

Est-ce un bug UIWebView (probablement pas)? Ou est-il quelque chose qui doit être fait pour rendre les choses « travail juste » comme dans Safari Mobile?

Était-ce utile?

La solution

J'ai trouvé quelque chose qui a fonctionné pour moi. Le problème est que lorsque UIWebView modifie son contenu Web d'orientation sont ZoomMed pour s'adapter à vue. Mais paramètre zoomscale de scrollview est pas mis à jour sous-vue correctement (ni sont mis à jour minimumZoomScale ni maximumZoomScale

Ensuite, nous devons le faire manuellement à 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;
    }
}

Hope this helps!

Autres conseils

J'ai essayé la solution de M Penades et cela semble fonctionner pour moi aussi.

La seule question que je fais l'expérience est que l'exécution de ce sur un 3Gs la rotation est malheureusement pas très lisse.

Je suis donc maintenant avec une approche différente:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {

[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];

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

}

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

essayer ce code, pour permettre à la taille de la teneur en augmentation UIWebView change niveau de zoom non significative (1.01) en mode paysage

findScrollViewInsideView: Procédé ajouté à l'appui iOS4

Je signale cela parce que j'ai aussi fait face au même problème et ici, je suis la Woks de Réponse M Penades Approach.M Penades bien que pour le cas si l'utilisateur n'a pas d'obliquité (Pincer) WebView puis tourner le dispositif et répéter ce processus de contenu Taille de UIWebView se réduire progressivement. de sorte que la question était venu en réponse de M Penades. donc j'ai fixé cette question aussi, et mon code est comme ci-dessous.

1) Pour cela, je mis la Gesture Pinch de sorte que lorsque l'utilisateur obliquité UIWebView pourrait vérifier la taille de Scaled UIWebView.         // Un Ce S'il vous plaît importer le protocole UIGestureRecognizerDelegate dans « .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;
  }

De retour OUI est garanti pour permettre la reconnaissance simultanée. NO n'est pas le renvoi garanti pour empêcher la reconnaissance simultanée, en tant que délégué de l'autre geste peut revenir OUI

 -(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 l'utilisateur Hase Pincez In / Out Web View dans ce cas qui se trouve juste que le facteur Zooming.     SO que WebView peut ajuster sa contentSize comme Oreintaion Changé.

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

}

Cela fonctionne parfaitement pour l'utilisateur même biaiser les UIWebView.

J'ai une solution à ce problème, mais je dois dire que je ne suis pas un grand fan de celui-ci. Il fonctionne très bien, mais la solution provoque effectivement un autre problème. J'ai un correctif pour le problème secondaire, mais il faut un peu d'effort.

Il suffit de garder à l'esprit que, depuis OS3.2 ou iOS4 (pas sûr) directe de sous-vue UIWebView est maintenant UIScrollView au lieu de UIScroller, de sorte que nous pouvons faire beaucoup plus avec elle. En outre, étant donné que l'accès subviews d'une vue n'est pas une action privée, ni utilise un sous-vue qui est casté en vue documenté que nous pouvons faire beaucoup avec le UIWebView sans enfreindre les règles.

Nous devons d'abord obtenir le UIScrollView du UIWebView:

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

Maintenant, nous devons changer le délégué de cette scrollview afin que nous puissions passer outre les appels des délégués ScrollView (qui peut effectivement être la cause d'un bogue secondaire à la suite de cette solution, que je vais partager dans un instant):

sview.delegate = self;

Maintenant, si vous essayez à ce point, le zoom est cassé. Nous devons mettre en œuvre une méthode de UIScrollViewDelegate pour y remédier. ajouter:

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

webBrowserView est en fait un UIWebBrowserView, mais ce n'est pas une classe documentée, donc nous allons juste de le traiter comme un UIView.

Maintenant exécutez votre application, zoomer puis effectuer un zoom arrière la page Web. Faire pivoter, et il devrait apparaître correctement.

Ce ne cause un bug assez grand, qui est peut-être pire que l'original.

Si vous effectuez un zoom puis faites pivoter, vous perdre la capacité de défilement, mais votre vue sera zoomée encore. Voici le correctif Pour compléter le tout.

Tout d'abord, nous avons besoin de garder une trace de quelques chiffres, et un drapeau défini:

J'ai ces défini dans mon fichier 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

Vous pouvez penser que vous pouvez simplement saisir ces chiffres de UIScrollView, mais quand vous avez besoin d'eux, ils ont changé, donc nous avons besoin d'eux stockés ailleurs.

Nous devons utiliser une autre méthode déléguée:

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

Maintenant, il pénètre dans un désordre que je ressens.

Nous devons suivre la rotation, de sorte que vous devrez ajouter à votre viewDidLoad, loadview, ou quelle que soit la méthode utilisée pour enregistrer les notifications:

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

et créer cette méthode:

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

Alors maintenant, chaque fois que vous faites pivoter webViewOrientationChange sera appelée. La raison performSelector est retardée de 0.0 secondes est parce que nous voulons appeler adjustWithZoomData sur le prochain runloop. Si vous appelez directement, le adjustWithZoomData ajustera pour l'orientation précédente.

Voici la méthode adjustWithZoomData:

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

Thats it! Maintenant, lorsque vous faites pivoter il maintiendra le zoom, et maintenir à peu près le décalage correct. Si quelqu'un veut faire le calcul sur la façon d'obtenir exactement décalage correct alors allez-y!

Je regardais en moi-même et a trouvé quelques informations supplémentaires:

Problèmes lors du changement de zoom:

  1. Safari ne souvent repeindre pas correctement (le cas échéant), même si le niveau de zoom changé.
  2. Modification des forces de largeur repeints.
  3. vous penseriez width = dispositif de largeur dans le paysage utiliserait 1024 mais il semble utiliser 768 (screen.width arrive aussi).

par exemple. si la largeur actuelle est 1024 et que vous souhaitez zoomer 1 à 1,5 dans le paysage, vous pouvez:

  • combinaison de changement de largeur et de zoom par exemple largeur de 2048 et de zoom pour 0,75
  • Largeur de changement à 1023 (aliasing laid?)
  • largeur de changement à dire 1023, puis de nouveau la ligne suivante à 1024 (à double repeindre, mais au moins une fenêtre est repeint).

Donc, apparemment, je ne pas utiliser la solution par M Penades à la fin (et a oublié de mettre à jour ce post! Désolé).

Ce que je l'ai fait de redimensionner le document entier (et modifier ma taille de la police de garder les choses proportionnelle). Cela semble résolu le problème.

Cependant, mon UIWebView est uniquement pour charger mon propre HTML & CSS à partir du système de fichiers iOS -. Si vous construisez un navigateur web à usage général, cette astuce ne fonctionne pas aussi 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;
    }
}

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

Contenu essentiel https://gist.github.com/d6589584944685909ae5

Lors de la rotation, essayez de régler le ScrollView zoomScale à 0. Voir ma réponse complète ici: contenu UIWebView pas ajusté à une nouvelle image après rotation

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top