Я создал приложение для iPhone скелета с UIWebView (Страница масштабов для Установки = ДА, shouldAutorotateToInterfaceOrientation = ДА) и загрузил веб-страницу, например, https://stackoverflow.com/
Вращение устройства показывает, что UIWebView автоизменен для установки ширине. Хороший.
Неправильный: Масштабирование в страницу и уменьшение. Теперь вращение устройства показывает UIWebView в странной ширине в одной из ориентации (если увеличение u среды, ширина портрета является странной, наоборот). Это поведение фиксируется только, когда Вы перешли к другой странице.
Корректный: Загрузите тот же URL в Мобильном Safari. Вращение работ и ширины соответствует независимо от осуществления изменения масштаба.
Действительно ли это - ошибка UIWebView (вероятно, не)? Или есть ли что-то, что должно быть сделано для создания вещей "просто работать" как в Мобильном Safari?
У меня есть решение этой проблемы, но я должен сказать, что я не большой его поклонник. Оно отлично работает, но решение фактически вызывает другую проблему. У меня есть решение для вторичной проблемы, но оно требует некоторых усилий.
Просто имейте в виду, что с 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;
}
Вот и все! Теперь при повороте он будет поддерживать масштаб и примерно сохранять правильное смещение. Если кто-то хочет посчитать, как получить точное правильное смещение, тогда вперед!