Как определить размер содержимого UIWebView?



у меня есть UIWebView разные (одна страница) содержание. Я хотел бы узнать CGSize содержимого для изменения размера моих родительских представлений соответствующим образом. Очевидное -sizeThatFits: к сожалению, просто возвращает текущий размер кадра webView.

679   16  

16 ответов:

оказалось, что моя первая догадка, используя -sizeThatFits: не был полностью неправ. Кажется, это работает, но только если фрейм webView установлен на минимальный размер перед отправкой -sizeThatFits:. После этого мы можем исправить неправильный размер кадра по размеру фитинга. Это звучит ужасно, но на самом деле это не так уж плохо. Поскольку мы делаем оба кадра изменения сразу после друг друга, вид не обновляется и не мерцает.

конечно, мы должны ждать, пока содержимое не будет загружено, поэтому мы поместите код в -webViewDidFinishLoad: метод делегата.

- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
    CGRect frame = aWebView.frame;
    frame.size.height = 1;
    aWebView.frame = frame;
    CGSize fittingSize = [aWebView sizeThatFits:CGSizeZero];
    frame.size = fittingSize;
    aWebView.frame = frame;

    NSLog(@"size: %f, %f", fittingSize.width, fittingSize.height);
}

Я должен указать, что есть другой подход (спасибо @GregInYEG) с помощью JavaScript. Не уверен, какое решение работает лучше.

из двух хакерских решений мне больше нравится это.

у меня есть другое решение, которое отлично работает.

С одной стороны, подход и решение Ortwin работает только с iOS 6.0 и более поздними версиями, но не работает правильно на iOS 5.0, 5.1 и 5.1.1, а с другой стороны, есть что-то, что мне не нравится и не может понять подход Ortwin, это использование метода [webView sizeThatFits:CGSizeZero] с параметром CGSizeZero : Если Вы читаете официальную документацию Apple об этом методе и его параметре, он ясно говорит:

реализация по умолчанию этого метода возвращает размер части прямоугольника границ представления. Подклассы могут переопределить этот метод, чтобы вернуть пользовательское значение, основанное на желаемой компоновке любых вложенных представлений. Например, объект UISwitch возвращает значение фиксированного размера, которое представляет стандартный размер представления коммутатора, а объект UIImageView возвращает размер изображения, которое он в настоящее время отображает.

я имею в виду, что он наткнулся на его решение без всякой логики, потому что читая документацию, параметр, переданный [webView sizeThatFits: ...] должен хотя бы иметь желаемое width. С его решением, желаемая ширина устанавливается в webView's кадр перед вызовом sizeThatFits С :

- (void)webViewDidFinishLoad:(UIWebView *)aWebView
{   
    aWebView.scrollView.scrollEnabled = NO;    // Property available in iOS 5.0 and later 
    CGRect frame = aWebView.frame;

    frame.size.width = 200;       // Your desired width here.
    frame.size.height = 1;        // Set the height to a small one.

    aWebView.frame = frame;       // Set webView's Frame, forcing the Layout of its embedded scrollView with current Frame's constraints (Width set above).

    frame.size.height = aWebView.scrollView.contentSize.height;  // Get the corresponding height from the webView's embedded scrollView.

    aWebView.frame = frame;       // Set the scrollView contentHeight back to the frame itself.
}

обратите внимание, что в моем, например,webView был встроен в пользовательский scrollView С другой webViews... Все это webViews их webView.scrollView.scrollEnabled = NO, и последний кусок кода, который я должен добавить был расчет height на contentSize моего scrollView эти webViews, но это было так же просто, как суммировать мои webView ' s frame.size.height вычисляется с помощью трюка, описанного выше...

воскрешая этот вопрос, потому что я нашел ответ Ортвина только на работу большую часть времени...

The webViewDidFinishLoad метод может быть вызван несколько раз, и первое значение возвращается sizeThatFits - это только часть того, что окончательный размер должен быть. Тогда по какой причине следующий звонок sizeThatFits, когда webViewDidFinishLoad пожары снова неверно вернут то же значение, что и раньше! Это произойдет случайным образом для того же контента, как если бы это была какая-то проблема параллелизма. Возможно это поведение изменилось с течением времени, потому что я строю для iOS 5, а также обнаружил, что sizeToFit работает примерно так же (хотя раньше этого не было?)

Я остановился на этом простом решении:

- (void)webViewDidFinishLoad:(UIWebView *)aWebView
{        
    CGFloat height = [[aWebView stringByEvaluatingJavaScriptFromString:@"document.height"] floatValue];
    CGFloat width = [[aWebView stringByEvaluatingJavaScriptFromString:@"document.width"] floatValue];
    CGRect frame = aWebView.frame;
    frame.size.height = height;
    frame.size.width = width;
    aWebView.frame = frame;
}

Swift (2.2):

func webViewDidFinishLoad(webView: UIWebView) {

    if let heightString = webView.stringByEvaluatingJavaScriptFromString("document.height"),
        widthString = webView.stringByEvaluatingJavaScriptFromString("document.width"),
        height = Float(heightString),
        width = Float(widthString) {

        var rect = webView.frame
        rect.size.height = CGFloat(height)
        rect.size.width = CGFloat(width)
        webView.frame = rect
    }
}

Update: я нашел, как упоминалось в комментариях, это, похоже, не улавливает случай, когда содержимое сократилось. Не уверен, что это правда для всего контента и версии ОС, попробуйте.

в Xcode 8 и iOS 10 для определения высоты веб-представления. вы можете получить высоту с помощью

- (void)webViewDidFinishLoad:(UIWebView *)webView
{
    CGFloat height = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
    NSLog(@"Webview height is:: %f", height);
}

или для Swift

 func webViewDidFinishLoad(aWebView:UIWebView){
        let height: Float = (aWebView.stringByEvaluatingJavaScriptFromString("document.body.scrollHeight")?.toFloat())!
        print("Webview height is::\(height)")
    }

простым решением было бы просто использовать webView.scrollView.contentSize но я не знаю, работает ли это с JavaScript. Если нет JavaScript используется это работает наверняка:

- (void)webViewDidFinishLoad:(UIWebView *)aWebView {
    CGSize contentSize = aWebView.scrollView.contentSize;
    NSLog(@"webView contentSize: %@", NSStringFromCGSize(contentSize));
}

AFAIK вы можете использовать [webView sizeThatFits:CGSizeZero] чтобы выяснить размер содержимого.

Это странно!

я протестировал оба решения sizeThatFits: и [webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] are не работает для меня.

тем не менее, я нашел интересный простой способ получить нужную высоту содержимого веб-страницы. В настоящее время я использовал его в своем методе делегата scrollViewDidScroll:.

CGFloat contentHeight = scrollView.contentSize.height - CGRectGetHeight(scrollView.frame);

проверено в iOS 9.3 симулятор / устройство, удачи!

EDIT:

фон: содержимое html вычисляется по моей строковой переменной и HTTP шаблон контента, загруженный методом loadHTMLString:baseURL:, никаких зарегистрированных сценариев JS нет.

для iOS10, я получал 0 (ноль) значение document.height Так document.body.scrollHeight это решение, чтобы получить высоту документа в WebView. Проблема может быть решена также для width.

я использую UIWebView это не подвид (и, следовательно, не является частью иерархии окон) для определения размеров содержимого HTML для UITableViewCells. Я обнаружил, что отключен UIWebView не сообщает его размер правильно с -[UIWebView sizeThatFits:]. Кроме того, как уже упоминалось в https://stackoverflow.com/a/3937599/9636, вы должны установить UIWebView ' s frameheight к 1, чтобы получить правильную высоту на всех.

если UIWebView ' s высота слишком большая (т. е. у вас есть он установлен до 1000, но размер содержимого HTML составляет всего 500):

UIWebView.scrollView.contentSize.height
-[UIWebView stringByEvaluatingJavaScriptFromString:@"document.height"]
-[UIWebView sizeThatFits:]

все возвращают a height из 1000.

чтобы решить мою проблему в этом случае, я использовал https://stackoverflow.com/a/11770883/9636, за что я послушно проголосовал. Однако я использую это решение только тогда, когда мой UIWebView.frame.width такой же -[UIWebView sizeThatFits:]width.

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

важным советом оказалось то, что UIWebView не сообщает свой размер правильно, пока не отображается на экране. Поэтому, когда я загружаю контент, я устанавливаю размер контента на доступную высоту экрана. Затем в viewDidAppear я обновляю размер содержимого scrollview до правильного значения. Это сработало для меня, потому что я вызываю loadHTMLString на локальном содержимом. Если вы используете loadRequest вам может потребоваться обновить contentSize в webViewDidFinishLoad также, в зависимости от того, как быстро извлекается html.

там нет мерцания, потому что только невидимая часть вид прокрутки изменяется.

Если ваш HTML содержит тяжелый

при использовании webview в качестве подвида где-то в scrollview вы можете установить ограничение высоты на некоторое постоянное значение, а затем сделать выход из него и использовать его как:

- (void)webViewDidFinishLoad:(UIWebView *)webView {
    webView.scrollView.scrollEnabled = NO;
    _webViewHeight.constant = webView.scrollView.contentSize.height;
}

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

код прост, как это:

-(void)webViewDidFinishLoad:(UIWebView *)webView
{

    //tell the width first
    webView.width = [UIScreen mainScreen].bounds.size.width;

    //use js to get height dynamically
    CGFloat scrollSizeHeight = [[webView stringByEvaluatingJavaScriptFromString:@"document.body.scrollHeight"] floatValue];
    webView.height = scrollSizeHeight;

    webView.x = 0;
    webView.y = 0;

    //......
}

также в iOS 7 для правильной работы всех упомянутых методов добавьте это в свой контроллер вида viewDidLoad способ:

if ([self respondsToSelector:@selector(automaticallyAdjustsScrollViewInsets)]) {
    self.automaticallyAdjustsScrollViewInsets = NO;
}

в противном случае ни один из методов не будет работать как следует.

Xcode8 swift3.1:

  1. установить высоту webView до 0 первый.
  2. на webViewDidFinishLoad делегат:

let height = webView.scrollView.contentSize.height

без шага 1, Если webview.высота > фактическое contentHeight, Шаг 2 вернет webview.высоты, но не contentsize.высота.

У меня такая же проблема, если UIWebView загружает разные URL-адреса, только получить max contentSize

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if (![keyPath isEqualToString:@"contentSize"]) return;
    CGSize vWebContentSize = [self.vcWeb.vWeb.wvBaseMain sizeThatFits:CGSizeZero];
    self.vcWeb.view.height = vWebContentSize.height;
    [self updateContainerContentSize];
}

Comments

    Ничего не найдено.