web-dev-qa-db-ja.com

向きが変わるとUIWebViewのサイズが正しく変更されませんか?

ビューコントローラのビューにサブビューとしてwebview、titleLabel、coverflowViewを追加しましたが、向きが変わったときにサイズを変更したいと思います。この方法でWebビューのフレームを変更しました。

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

アプリケーションを縦向きで起動した場合、iPadをorientationLandscapeからorientationPortraitに、またはorientationPortraitからorientationLandscapeに回転すると、コンテンツのサイズが変更されましたが、横向きでアプリケーションを起動したときにコンテンツのサイズが変更されないほど奇妙です...しかし、 NSLogは、フレームが変更されたことを示します。 titleLabelとcoverflowViewに関しては、正しくサイズ変更されます。それがcssのせいなのか疑問ですが、私はcssを使用して、Webビューの高さと幅に応じてコンテンツのスタイルを制御しています。コードは以下のとおりです。

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

}
17
user424714

私はまったく同じ問題を抱えていたので、この問題を追跡するために約2日を費やしました。ポートレートモードで開始した場合、ビューのサイズがランドスケープに正しく変更されることがわかりました。ただし、横向きモードでビューを開始すると、縦向きでも同じサイズが維持されます。

ビューがデバイスの幅全体である場合は、次のメタタグを追加するだけで機能します。

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

しかし、私の場合、UIWebViewは非標準サイズです。ビューポートをdevice-widthに設定すると、さらに悪化します。 javascriptを使用してビューポートを動的に設定することで、すべてを正しく機能させることができました。これは、UIWebViews親ビューのlayoutSubviews中に実行する必要があります。 willRotateToInterfaceOrientationで実行できますが、willRotateで実行すると、一部のサイズとインターフェイスが正しくセットアップされない可能性があることがわかりました。最初にそこで試して、アニメーションがどのように機能するかを確認してください。

このコードは、ビューポートサイズを現在のフレームサイズに設定するだけです。表示しているHTMLには、すでにmeta viewportタグが付いている必要があります(上記のとおり)。 HTMLを編集できない場合は、JavaScriptを介してHTMLを追加する他の方法があります。最も簡単なのは、メタタグを<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に対して正しく動作するようになりました。

51

@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
Kevin Schroeder

私は同様の問題を抱えていますが、それでもこれに対する本当の解決策を見つけることができません。 UIWebViewでreloadを呼び出して、スケールページを合わせて問題を回避します。

[webView reload];
1
Khomsan

他の人が同じ問題を抱えている場合は、ヘッドサップを与えるだけです。

HTMLがすでにレンダリングされているため、Webビューのサイズが適切に変更されません(これが完全に正しいかどうかはわかりませんが、Webビュー自体のバグである可能性があります)が、とにかく。 webviewhtmlの本文の幅を変更するメソッドを作成しました。

- (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
Rasmus Styrk

私は クリストパーの答え を試し、彼のOOCコードをSwiftに変換しましたが、機能しませんでした。

最後に、画面サイズが変更された場合は、UIWebViewにWebページを再読み込みさせる必要があります。それはハックかもしれませんが、とにかく動作します。この答えが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
T.Liu

私はちょうど同じ問題を抱えていました。

私のために働いた解決策は、設定することでした:

webView.scalesPageToFit = YES;
0
Raskal1979

また、横向きから縦向きに切り替えるときに、UIWebViewのコンテンツのサイズが適切に設定されないという問題も発生していました。

しばらく探し回った後、私は私の答えを見つけました:

「これを処理する方法の1つは、サイズ変更後にコンテンツをリロードすることです。「リロード」とは、UIWebViewに組み込まれているリロード関数ではなく、loadHTMLStringの実際の呼び出しを意味します。baseURL: (または、コンテンツを最初にロードするために使用する方法)。」 エージェントゴールドのAppleサポートフォーラム への投稿

0
Brian Gershon