UIWebView не правильно изменить размер при изменении ориентации? - PullRequest
17 голосов
/ 15 мая 2011

Я добавил веб-представление, titleLabel и coverflowView в представление viewcontroller в качестве его подпредставлений, я хочу, чтобы оно меняло размер при изменении ориентации.Я изменил рамку веб-просмотра следующим способом:

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

его содержимое изменило размер при повороте iPad из альбомной ориентации, ориентации или горизонтальной ориентации, если я запускаю приложение с книжной ориентацией, но это настолько странно, чтоего содержимое не изменяется при запуске приложения с альбомной ориентацией ... Но NSLog показывает, что кадр изменился.Что касается titleLabel и coverflowView, они изменяют размер правильно.Я сомневаюсь, что это из-за css? Я использую css для управления стилем контента в соответствии с высотой и шириной веб-просмотра. Кто-нибудь может мне помочь найти причину?код ниже:

- (void)willRotateToInterfaceOrientation: (UIInterfaceOrientation)toInterfaceOrientation duration: (NSTimeInterval)duration {
double i = 0;
NSInteger  width=self.view.frame.size.width;
NSInteger  height=self.view.frame.size.height;
NSLog(@"view :%@",[self.view description]);
switch (toInterfaceOrientation){
    case UIInterfaceOrientationPortrait:
    {    
        NSLog(@"rotate to Portrait");
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
            self.docView.frame=CGRectMake(0, 50, width+20, height-70);
            self.toolbar.frame=CGRectMake(0, 0,height , 50);
            for (UIView * view in [toolbar subviews]) {
                if ([view isKindOfClass:[UIButton class]] && view.tag==kBackButtonTag){
                    view.frame=CGRectMake(width-60, 6, 50, 36);

                }else if([view isKindOfClass:[UIButton class]] && view.tag==kReloadButtonTag){
                    view.frame=CGRectMake(width-160, 6, 80,36 );
                }
            }
            [coverflow setFrame:CGRectMake(0, 0 , width+20, height/2-50)];
            [titleLabel setFrame:CGRectMake(width/2-40,height/2-100, 100, 20)];
            if ([[[UIDevice currentDevice]model]isEqualToString:@"iPad"]) {
                self.viewer.frame=CGRectMake(0, 0, 768, 1004);
            }else{
                self.viewer.frame=CGRectMake(0, 0, 320, 480);
            }
        }
        i=0;
    }break;
    case UIInterfaceOrientationPortraitUpsideDown:
    {
        NSLog(@"rotate to PortraitUpsideDown");
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
            self.docView.frame=CGRectMake(0, 50, width+20, height-70);
            self.toolbar.frame=CGRectMake(0, 0,height , 50);
            for (UIView * view in [toolbar subviews]) {
                if ([view isKindOfClass:[UIButton class]] && view.tag==kBackButtonTag)  {
                    view.frame=CGRectMake(width-60, 6, 50, 36);

                }else if([view isKindOfClass:[UIButton class]] && view.tag==kReloadButtonTag){
                    view.frame=CGRectMake(width-160, 6, 80,36 );
                }
            }

            [coverflow setFrame:CGRectMake(0, 0 , width+20, height/2-50)];
            [titleLabel setFrame:CGRectMake(width/2-40,height/2-100, 100, 20)];
            if ([[[UIDevice currentDevice]model]isEqualToString:@"iPad"]) {
                self.viewer.frame=CGRectMake(0, 0, 768, 1004);
            }else{
                self.viewer.frame=CGRectMake(0, 0, 320, 480);
            }

        }

        i=180;
    }   break;
    case UIInterfaceOrientationLandscapeLeft:{

        NSLog(@"rotate to LandscapeLeft");
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
       //     self.coverflow.frame=CGRectMake(0, 0, height+20, width-20);
            self.docView.frame=CGRectMake(0, 50, height+20, width-70);
            self.toolbar.frame=CGRectMake(0, 0,height+20 , 50);
            for (UIView * view in [toolbar subviews]) {
                if ([view isKindOfClass:[UIButton class]] && view.tag==kBackButtonTag)  {
                    view.frame=CGRectMake(height-60, 6, 50, 36);
                    NSLog(@"button %@",[view description]);
                }else if([view isKindOfClass:[UIButton class]] && view.tag==kReloadButtonTag){
                    view.frame=CGRectMake(height-160, 6, 80,36 );
                }
            }
            [coverflow setFrame:CGRectMake(0, 0 , height+20, width/2-50)];
            [titleLabel setFrame:CGRectMake(height/2-40,width/2-80, 100, 20)];
            if ([[[UIDevice currentDevice]model]isEqualToString:@"iPad"]) {
                self.viewer.frame=CGRectMake(0, 0, 1024, 748);
            }else{
                self.viewer.frame=CGRectMake(0, 0, 480, 320);
            }
        }

        i = 90;
    }break;
    case UIInterfaceOrientationLandscapeRight:{
        NSLog(@"rotate to LandscapeRight");
        if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
        //    self.coverflow.frame=CGRectMake(0, 0, height+20, width-20);
            self.docView.frame=CGRectMake(0, 50, height+20, width-70);
            self.toolbar.frame=CGRectMake(0, 0,height+20 , 50);
            for (UIView * view in [toolbar subviews]) {
                if ([view isKindOfClass:[UIButton class]] && view.tag==kBackButtonTag)  {
                    view.frame=CGRectMake(height-60, 6, 50, 36);
                }
                else if([view isKindOfClass:[UIButton class]] && view.tag==kReloadButtonTag){
                    view.frame=CGRectMake(height-160, 6, 80,36 );
                }
            }
            [coverflow setFrame:CGRectMake(0, 0 , height+20, width/2-50)];
            [titleLabel setFrame:CGRectMake(height/2-40,width/2-80, 100, 20)];
            if ([[[UIDevice currentDevice]model]isEqualToString:@"iPad"]) {
                self.viewer.frame=CGRectMake(0, 0, 1024, 748);
            }else{
                self.viewer.frame=CGRectMake(0, 0, 480, 320);
            }
        }

        i = -90;
    }break;
}

//[webViewController willRotateToInterfaceOrientation:toInterfaceOrientation duration:duration];
// [self.view setNeedsDisplay];
//   NSLog(@"coverflowView :%@",[self.coverflow description]);
   NSLog(@"webview :%@",[viewer description]);
    [viewer stringByEvaluatingJavaScriptFromString:[NSString stringWithFormat:@"window.__defineGetter__('orientation',function(){return %f;});",i]];
    [viewer stringByEvaluatingJavaScriptFromString:@"var e = document.createEvent('Events'); e.initEvent('orientationchange', true, false); document.dispatchEvent(e); "];    
}




- (void)viewDidLoad {
self.view.clipsToBounds=YES;
self.view.autoresizesSubviews=YES;
// self.view.autoresizingMask=UIViewAutoresizingNone;

viewer=[[UIWebView alloc]initWithFrame:self.view.bounds];

[self.view addSubview:viewer];
 viewer.delegate=self;
 viewer.scalesPageToFit=NO;
 viewer.autoresizesSubviews=NO;
 viewer.autoresizingMask=UIViewAutoresizingNone;
viewer.dataDetectorTypes=0;
// viewer.autoresizingMask=UIViewAutoresizingFlexibleWidth |UIViewAutoresizingFlexibleHeight;
NSLog(@"webView :%@",[viewer description]);
//  [viewer setFrame:CGRectMake(0, self.view.bounds.size.height/2 , self.view.bounds.size.width, self.view.bounds.size.height/2)];
//  [viewer setBounds:CGRectMake(0, self.view.bounds.size.height/2 , self.view.bounds.size.width, self.view.bounds.size.height/2)];

UIScrollView *scroller=[viewer.subviews objectAtIndex: 0];
if (scroller) {
    scroller.alwaysBounceVertical=NO;
    scroller.bounces=NO;
    scroller.scrollEnabled=NO;   
}

[self viewHomePage];
//[self createCoverFlowView];
[self createPopView];
//[self setHomeButtonPosition]; 
//[self setSettingButtonPosition];

#if __IPHONE_OS_VERSION_MIN_REQUIRED > 30000
UILongPressGestureRecognizer* longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPress:)];
[self.view addGestureRecognizer:longPress];
longPress.minimumPressDuration=2.0;
longPress.delegate = self;
longPress.cancelsTouchesInView = NO;
longPress.allowableMovement=20;
[longPress release];  

UITapGestureRecognizer* singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.view addGestureRecognizer:singleTap];
singleTap.delegate = self;
singleTap.cancelsTouchesInView = NO;
[singleTap release];  
#endif
//[viewer setOpaque:YES];      //透明
[super viewDidLoad];

}

Ответы [ 7 ]

51 голосов
/ 24 мая 2011

Я потратил около двух дней, пытаясь отследить эту проблему, поскольку у меня была точно такая же проблема. Я обнаружил, что мой вид, если он начался в портретном режиме, будет корректно изменен на альбомный. Но если бы я запустил вид в альбомном режиме, он бы сохранил тот же размер в портретном.

Если ваш вид на всю ширину устройства, просто добавьте следующий метатег.

<meta name="viewport" content="width=device-width" />

Но в моем случае наш UIWebView имеет нестандартный размер. Установка окна просмотра на device-width только ухудшает ситуацию! Я смог заставить все работать правильно, динамически устанавливая область просмотра с помощью JavaScript. Это должно быть сделано во время layoutSubviews родительского представления UIWebViews. Вы можете сделать это в willRotateToInterfaceOrientation, но я выяснил, что если вы сделаете в willRotate, некоторые размеры и интерфейсы могут быть настроены неправильно. Сначала попробуйте там и посмотрите, как работает анимация.

Код просто устанавливает размер области просмотра на текущий размер кадра. HTML-код, который вы просматриваете, должен уже иметь тег meta viewport (как указано выше). Если вы не можете редактировать HTML, есть другие способы добавить его через JavaScript. Самый простой - просто добавить метатег в тег <head>. Затем используйте следующий код, ПОСЛЕ того, как вы правильно установили кадр:

 // assuming your self.viewer is a UIWebView
[self.viewer stringByEvaluatingJavaScriptFromString:
     [NSString stringWithFormat:
     @"document.querySelector('meta[name=viewport]').setAttribute('content', 'width=%d;', false); ",
      (int)self.viewer.frame.size.width]];

Вы можете добавить другие элементы видового экрана, если вы не хотите, чтобы пользователь масштабировал, или вы хотите установить максимальный масштаб. Это привело к правильному поведению представления для нашего UIWebView.

1 голос
/ 22 ноября 2012

Я одобрил ответ @ christophercotton, так как он работал.Но я также обнаружил, что могу решить проблему, подобную этой, без управления объектом webview.Его решение поставило меня на правильный путь для моей проблемы.

        var el = $('meta[name=viewport]');
    if (window.orientation == 90 || window.orientation == -90) {
        el.attr('content', 'width=device-height');
    } else {
        el.attr('content', 'width=device-width');
    }

Это работает в iOS.Не пробовал в Android (для тех, кто использует PhoneGap).

1 голос
/ 09 ноября 2011

Просто предупреждаю, если у других такая же проблема.

Веб-представление не будет правильно изменять размер, потому что HTML-код уже визуализирован (я не уверен, что это полностью верно, возможно, это просто ошибка в самом веб-представлении), но в любом случае.Я сделал метод, который изменяет ширину тела html webview:

- (void) resizeHtml
{
     NSString *jsString = [[NSString alloc] initWithFormat:@"document.getElementsByTagName('html')[0].style.width= '%dpx'", (int) _frame.size.width];

    [self.webView stringByEvaluatingJavaScriptFromString:jsString];
    [jsString release];
}

На iphone это работает нормально, но на ipad мне пришлось это сделать

- (void) reloadHtml
{
    NSString *html = [webView stringByEvaluatingJavaScriptFromString:@"document.documentElement.outerHTML"];

    if(html == nil || [html isEqualToString:@""] || [html length] < 100)
        [self.webView reload];

    [self.webView loadHTMLString:html baseURL:[NSURL URLWithString:@"some base url"]];
}

Вымог бы также использовать [self.webview reload], но это сделало бы еще один запрос к серверу, и я думаю, что это плохо; -)

Надеюсь, это поможет!

1 голос
/ 15 мая 2011

У меня похожая проблема, и я до сих пор не могу найти реальное решение этой проблемы. Я вызываю reload в UIWebView, чтобы обойти эту проблему, поместив страницу масштабирования на нужную сумму.

[webView reload];
0 голосов
/ 26 апреля 2016

Я пытался ответ Кристопера , переводя его код OOC в Swift, но не работал.

Наконец, я должен заставить UIWebView перезагрузить веб-страницу, если размер экрана изменился. Это может быть взлом, но все равно работает. Жаль, что этот ответ не может помочь разработчикам Swift более или менее. Приведенная ниже функция принадлежит вашему UIViewController.

override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
    super.viewWillTransitionToSize(size, withTransitionCoordinator: coordinator)
    coordinator.animateAlongsideTransition(nil, completion: {context in
        self.webView.reload()            
    })
}
0 голосов
/ 14 августа 2014

У меня была та же проблема.

Решение, которое работало для меня, было установить:

webView.scalesPageToFit = YES;
0 голосов
/ 22 июля 2011

У меня также возникла проблема с неправильным размером содержимого UIWebView при переключении с альбомного на портретное.

Пройдя немного охоты, я нашла ответ:

«Один из способов, который я нашел, - это перезагрузить содержимое после изменения размера. Когда я говорю« перезагрузить », я не имею в виду встроенную функцию перезагрузки в UIWebView, я имею в виду фактический вызов loadHTMLString : baseURL: (или какой метод вы используете для начальной загрузки вашего контента). " Сообщение Агента Голда на форуме поддержки Apple

...