iPhone Uiwebview ширина не подходит после операции масштабирования + изменение UIInterfaceOrentation

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

Вопрос

Я создал приложение для iPhone с голыми костями с UIWEBVIEW (Page Scales, чтобы соответствовать = Да, необходимо) и загрузить веб-страницу, например, https://stackoverflow.com/

Вращающиеся устройство показывает, что UIWEBVIEW является автоматически изменена для соответствия ширине. Хорошо.

Неверный: Zoom на страницу и уменьшить. Время вращения устройства показывает UiWebView в странной ширине в одной из ориентаций (если Zoom в ландшафте, портретная ширина странная, наоборот). Это поведение фиксируется только при переходе на другую страницу.

Правильный: Загрузите один и тот же URL в мобильном Safari. Вращающиеся работы и ширина подходит независимо от увеличения упражнений.

Это ошибка UiWebView (вероятно, нет)? Или есть что-то, что нужно сделать, чтобы сделать вещи «просто работать», как в мобильном Safari?

Это было полезно?

Решение

Я нашел что-то, что сработало для меня. Проблема в том, что когда UiWebView изменяет свою ориентацию Web содержимое, ZOOMEMED соответствует ViewStort. Но параметр ZOOOLSCALE SCROLLVIVE SUBVVIEW не обновляется правильно (и не обновляются MinmerZoomscale, ни максимамизма

Тогда нам нужно сделать это вручную в 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;
    }
}

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

Другие советы

Я попробовал решение из M слесалки, и это, кажется, работают для меня.

Единственным вопросом, который я испытываю, является то, что при запуске этого на 3GS вращение, к сожалению, не очень гладко.

Я поэтому сейчас использую другой подход:

- (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation {

[super didRotateFromInterfaceOrientation:fromInterfaceOrientation];

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

}

С уважением,
Ральф

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

Попробуйте этот код, оно незначительно меняет уровень масштабирования (1.01), чтобы позволить UiWebView увеличить размер содержимого в режиме ландшафта

findscrollviewinsideview: метод добавлен для поддержки iOS4

Я размещаю это, потому что я также столкнулся с той же проблемой, и здесь я следую M Penades Подход.M Penades Ответ Woks Хорошо только для случая, если пользователь не перекоснут (ущипнуть), веб-просмотр, затем поверните устройство и повторите этот процесс. Затем размер контента UIWEBVIEW уменьшится постепенно. Так что это была проблема в M Penades Отвечать. Поэтому я тоже исправил этот вопрос, и мой код ниже.

1) Для этого я установил мочевую жест, так что, когда пользователь перекосает UIWEBVIEW может проверить масштабированный размер UIWEBVIEW. // один это, пожалуйста, импортируйте UIGestureRecognizerDelegate Протокол в '.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;
  }

Возвращая да гарантированно разрешено одновременное распознавание. Возвращая нет не гарантируется предотвращение одновременного распознавания, так как делегат другого жеста может вернуться да

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

Если пользователь Hase ущипнет / выгнал вид веб-вида в этом случае, просто установите этот коэффициент масштабирования. Так что WebView может настроить его содержимое в виде 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;
     }
  }

}

Это отлично работает для даже пользовательского языка UiWebView.

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

Просто имейте в виду, что, поскольку OS3.2 или iOS4 (не уверены, какие) UiWebView's Direct SubVView теперь UiscrollView вместо UIScroller, поэтому мы можем сделать намного больше с ним. Кроме того, поскольку доступ к доступу доступа к представлению не является частным действием, ни использует подзвучай, который избита в виде документированного представления, мы можем многое сделать с UIWEBVIVE без нарушения правил.

Сначала нам нужно получить UiscrollView от UIWEBVIEW:

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

Теперь нам нужно изменить делегат этого ScrollView, поэтому мы можем переопределить вызовы делегирования ScrollView (что, возможно, может быть причиной вторичной ошибки в результате этого решения, которое я буду делиться в настоящее время):

sview.delegate = self;

Теперь, если вы попробуете его в этот момент, масштабирование сломано. Нам нужно реализовать метод uiscrollviewDelegate для его исправления. Добавить:

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

WebBrowsiview - это на самом деле uiwebbrosiview, но это не документированный класс, поэтому мы просто собираемся лечить его как UIView.

Теперь запустите свое приложение, увеличьте, а затем уменьшите веб-страницу. Вращаться, и он должен появиться правильно.

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

Если вы масштабируете, а затем поверните, вы потеряете прокрутку, но ваш взгляд будет увеличен. Вот исправление, чтобы завершить все это.

Во-первых, нам нужно отслеживать несколько чисел и иметь флаг, определенный:

Я имел это определено в моем файле 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

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

Нам нужно использовать другой метод делегата:

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

Теперь он попадает в беспорядок, который я чувствую.

Нам нужно отслеживать вращение, поэтому вам нужно добавить это в свою программу ViewDidload, LoadView, или любой метод, который вы используете для регистрации уведомлений:

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

и создать этот метод:

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

Так что теперь в любое время вы поворачиваете WebVieworientationChange, будут вызываться. Причина PerformentSelector задерживается в течение 0,0 секунды, потому что мы хотим позвонить на RedWithzoomData на следующем runloop. Если вы назовите это напрямую, настройка readwithzoomdata отрегулирует для предыдущей ориентации.

Вот метод корректировки для настройки:

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

Вот и все! Теперь, когда вы вращаете, он будет поддерживать увеличение, и примерно поддерживает правильное смещение. Если кто-то хочет сделать математику о том, как получить точное правильное смещение, а затем пойти на это!

Я смотрел в это сам и узнал еще несколько информации:

Вопросы при изменении зума:

  1. Safari часто не является правильно перерасходованным (если вообще), хотя уровень масштабирования изменился.
  2. Изменение ширины заставляет перекраску.
  3. Вы бы подумали, что ширина = ширина устройства в ландшафте будет использовать 1024, но, похоже, используется 768 (Screen.width тоже происходит).

Например, если тока ширина 1024, и вы хотите увеличить от 1 до 1,5 в ландшафте, вы можете:

  • Изменить комбинацию ширины и увеличения, например, ширина до 2048 и увеличение 0,75
  • Изменить ширину до 1023 (уродливой псевдонимы?)
  • Измените ширину, чтобы сказать 1023, затем следующую строку назад до 1024 (двойной перекраск, но, по крайней мере, окно перекрашено).

Так что, по-видимому, я не использовал решение на карами в конце (и забыл обновить этот пост! Извините).

То, что я сделал, это было разместить весь документ (и изменить свой размер шрифта, чтобы держать вещи соразмерными). Это, по-видимому, исправило проблему.

Тем не менее, мой UIWEBVIEW предназначен только для загрузки моих собственных HTML & CSS из файловой системы iOS - если вы создаете веб-браузер общего назначения, этот трюк также может работать.

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

И app.csss.

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.

На вращении попробуйте установить ScrollView Zoomscale до 0. См. Мой полный ответ здесь: Контент UIWEBVIEW не настроен на новый кадр после ротации

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top