ширина iPhone UIWebView не соответствует после изменения масштаба операции + изменение UIInterfaceOrientation

Я создал приложение для iPhone скелета с UIWebView (Страница масштабов для Установки = ДА, shouldAutorotateToInterfaceOrientation = ДА) и загрузил веб-страницу, например, https://stackoverflow.com/

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

Неправильный: Масштабирование в страницу и уменьшение. Теперь вращение устройства показывает UIWebView в странной ширине в одной из ориентации (если увеличение u среды, ширина портрета является странной, наоборот). Это поведение фиксируется только, когда Вы перешли к другой странице.

Корректный: Загрузите тот же URL в Мобильном Safari. Вращение работ и ширины соответствует независимо от осуществления изменения масштаба.

Действительно ли это - ошибка UIWebView (вероятно, не)? Или есть ли что-то, что должно быть сделано для создания вещей "просто работать" как в Мобильном Safari?

14
задан Community 23 May 2017 в 10:27
поделиться

1 ответ

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

Просто имейте в виду, что с OS3.2 или iOS4 (не уверен, что именно) прямое вложенное представление UIWebView теперь UIScrollView, а не UIScroller, поэтому мы можем делать с ним гораздо больше. Кроме того, поскольку доступ к вложенным видам представления не является приватным действием, как и использование вложенного вида, созданного как документированное представление, мы можем многое сделать с UIWebView, не нарушая правил.

Сначала нам нужно получить 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;
}

webBrowserView на самом деле является UIWebBrowserView, но это не документированный класс, поэтому мы будем рассматривать его как 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. Причина задержки performSelector на 0.0 секунды заключается в том, что мы хотим вызвать adjustWithZoomData на следующем цикле выполнения. Если вызвать его напрямую, adjustWithZoomData будет корректировать предыдущую ориентацию.

Вот метод adjustWithZoomData:

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

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

0
ответ дан 1 December 2019 в 12:12
поделиться
Другие вопросы по тегам:

Похожие вопросы: