iOS开发WKWebView计算内容高度2018-08-02

一,先计算WebView的内容高度

1,想当然的方法1

既然想计算webView中网页的高度,那就在网页加载完成的时候,直接返回
scrollView.contentSize.height。

#pragma mark - WKNavigationDelegate
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{ 
    NSLog(@"加载完成");
    CGFloat contentHeight = self.webView.scrollView.contentSize.height;
}

这个结果返回值:是0。
为啥不行,这里面先理解成这里的加载完成只是网页请求解析完成,还没有放在WebView的scrollView上显示!

2,一般方法

一般我们计算webView的高度,网上有栗子是通过调用网页的方法来实现,如下:

#pragma mark - WKNavigationDelegate
// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    NSLog(@"加载完成");
    
    [webView evaluateJavaScript:@"document.body.scrollHeight"completionHandler:^(id _Nullable result,NSError * _Nullable error){
        
        _wbContentHeight = [result floatValue];
        NSLog(@"scrollHeight高度:%.2f",[result floatValue]);
    }];

    [webView evaluateJavaScript:@"document.body.offsetHeight"completionHandler:^(id _Nullable result,NSError * _Nullable error){
        
        NSLog(@"offsetHeight高度:%.2f",[result floatValue]);
    }];
}
2016-11-08 11:41:50.572862 WebView内容高度计算[18606:6890472] scrollHeight高度:5497.00
2016-11-08 11:41:50.574534 WebView内容高度计算[18606:6890472] offsetHeight高度:5465.00

通过调用html的body标签的属性,我们去确实可以获取高度,这里分别用了:scrollHeightoffsetHeight。如果想要计算webView上scrollView的contentSize的height 那么用scrollHeight这个计算还是挺准确的,这个offsetHeight计算的会查几十个高度(网页不同差的不同,这个原因我不知道)。

但是,这只是一般方法,只能说如果你的web页面是你们的H5工程师给你们写的(其实特指页面不能缩放的),那是可以的,没问题。如果你的页面是顺便一个网页,比如oschina主页https://www.oschina.net,这会你计算,这个方法返回的值和你scrollView真正能滚动的区域就差很远了!

为什么了?
因为我们的WKWebView会根据网页的大小来自动缩放网页(UIWebView可以通过设置scalesPageToFit来开启),而这个方法计算的是缩放前的网页滚动区域大小,所以我们如果想计算出缩放后的高度,就要算出缩放比,然后乘上这个缩放比。关键是这个缩放比怎么拿?UIWebView我们没有直接属性可拿这个缩放比,而WKWebView有magnification属性但是phone不可用😱,我们可以算出宽度,再根据webView的宽度算出,下面是代码

#pragma mark - WKNavigationDelegate

// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    NSLog(@"加载完成");
    //这个方法也可以计算出webView滚动视图滚动的高度
    [webView evaluateJavaScript:@"document.body.scrollWidth"completionHandler:^(id _Nullable result,NSError * _Nullable error){
        
        CGFloat ratio =  CGRectGetWidth(self.wkWebView.frame) /[result floatValue];
        NSLog(@"scrollWidth高度:%.2f",[result floatValue]);
        
        [webView evaluateJavaScript:@"document.body.scrollHeight"completionHandler:^(id _Nullable result,NSError * _Nullable error){
            
            NSLog(@"scrollHeight高度:%.2f",[result floatValue]*ratio);
            
        }];
        
    }];
}

3,终极方法

有没有更好的方法,当然有!哈哈哈哈,及时使用KVO,监听scrollView.contentSize

[self.wbScrollView addObserver:self forKeyPath:@"contentSize" 
options:NSKeyValueObservingOptionNew context:nil];
#pragma mark  - KVO回调
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    //更具内容的高重置webView视图的高度
    NSLog(@"Height is changed! new=%@", [change valueForKey:NSKeyValueChangeNewKey]);
    NSLog(@"tianxia :%@",NSStringFromCGSize(self.wbScrollView.contentSize));
    CGFloat newHeight = self.wbScrollView.contentSize.height;

控制台输出

2016-11-09 17:28:25.850029 WebView内容高度计算[19613:7236291] Height is changed! new=NSSize: {998, 2740}
2016-11-09 17:28:25.850227 WebView内容高度计算[19613:7236291] tianxia :{998, 2740}
2016-11-09 17:28:25.850916 WebView内容高度计算[19613:7236291] Height is changed! new=NSSize: {320, 878.5}
2016-11-09 17:28:25.850987 WebView内容高度计算[19613:7236291] tianxia :{320, 878.5}
2016-11-09 17:28:25.927509 WebView内容高度计算[19613:7236291] Height is changed! new=NSSize: {320, 878.5}
2016-11-09 17:28:25.927660 WebView内容高度计算[19613:7236291] tianxia :{320, 878.5}
2016-11-09 17:28:25.927836 WebView内容高度计算[19613:7236291] Height is changed! new=NSSize: {320, 878.5}

第一次计算出的2740就是通过方法2不乘以缩放比得到的值!

二,下方放入TableView做评论列表

1,解决webView 和 table滚动的协调性

思路就是,把WebView作为TableView的TableHeader。这里我们控制WebView最高也就是屏幕的高,如果内容大于WebView的高度(所以有了上面计算webView的内容高度),需要滚动显示WebView的内容,直到滚动到最底端的时候,才滚动出tableView!
初始状态控制:
初始状态我们需要把webView的scrollView的回弹bounces一直禁止掉,防止和TableView的回弹冲突。

    self.wbScrollView = self.wkWebView.scrollView;
    self.wbScrollView.bounces = NO;

我们只需要监听tableView的滚动事件,在他的偏移度为<<=0的时候,我们要让webView的scrollVIew可以滚动,同时关闭tableView的回弹bounces,在table的偏移度>0的时候,就取反,这样我们可以控制webView和table滚动的协调性。

#pragma mark - UIScrollViewDelegate
-(void)scrollViewDidScroll:(UIScrollView *)scrollView{
    
    if ([scrollView isEqual:self.tableView]) {
        NSLog(@"tableView");
        CGFloat yOffSet = scrollView.contentOffset.y;
        NSLog(@"偏移%.2f",yOffSet);
        if (yOffSet <= 0) {
            self.wbScrollView.scrollEnabled = YES;
            self.tableView.bounces = NO;
        }else{
            self.wbScrollView.scrollEnabled = NO;
            self.tableView.bounces = YES;
        }
    }
}

2,解决网页动态加载内容高度变化问题

网页加载的时候在加载完成会调用webView 的delegate ,这时候我们可以计算出网页的高度,重置我的webView的frame 的高(使用方法2),但是我们可能会忽视一个问题,如果网页中有图片的话,因为图片大多数都是异步加载的,在webView加载完成的时候计算出的内容高度并不包含图片的高度,所以我们要设置一个监听KVO,来监听内容高度的变化!

#pragma mark - WKNavigationDelegate

// 页面加载完成之后调用
- (void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation{
    NSLog(@"加载完成");
    //这个方法也可以计算出webView滚动视图滚动的高度
    [webView evaluateJavaScript:@"document.body.scrollWidth"completionHandler:^(id _Nullable result,NSError * _Nullable error){
        
        NSLog(@"scrollWidth高度:%.2f",[result floatValue]);
        CGFloat ratio =  CGRectGetWidth(self.wkWebView.frame) /[result floatValue];
        
        [webView evaluateJavaScript:@"document.body.scrollHeight"completionHandler:^(id _Nullable result,NSError * _Nullable error){
            NSLog(@"scrollHeight高度:%.2f",[result floatValue]);
            NSLog(@"scrollHeight计算高度:%.2f",[result floatValue]*ratio);
            CGFloat newHeight = [result floatValue]*ratio;
            
            [self resetWebViewFrameWithHeight:newHeight];

            //KVO监听网页内容高度变化
            if (newHeight < CGRectGetHeight(self.view.frame)) {
                //如果webView此时还不是满屏,就需要监听webView的变化  添加监听来动态监听内容视图的滚动区域大小
                [self.wbScrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
            }
        }];
        
    }];
}

在监听回调中,重置(Reset) webView的frame。

#pragma mark  - KVO回调
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    //更具内容的高重置webView视图的高度
    CGFloat newHeight = self.wbScrollView.contentSize.height;
    NSLog(@"kvo算出的高度啊:%.f",newHeight);
    [self resetWebViewFrameWithHeight:newHeight];
}

这样我们就可以完美的把webView和tableView衔接起来了!
顺便说一下,重置完webView的frame要刷新table 因为webView是table的header!
完整代码下载地址:<链接: https://pan.baidu.com/s/1oGs1tE1JIryVdQKgQrdGEg 密码: rgff>
代码中,方案二是这篇博客,方案一思路是一个scrollView上面放webView下面放tableView,发现在控制滚动冲突上不是多理想

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • 1、通过CocoaPods安装项目名称项目信息 AFNetworking网络请求组件 FMDB本地数据库组件 SD...
    阳明先生_X自主阅读 15,969评论 3 119
  • 有人调侃我最近写的都是理财,对理财不感冒到开卖理财险,开始算计了,战场有变化。我在此做个解释。 ...
    一团泥巴阅读 255评论 0 0
  • 我一直谦卑隐忍地跟随在长辈身后,时不时表现出恰到好处的附和恭维。掌握拳柄的人认为:只要没有人指出,他就永远不容置疑...
    scholarismart阅读 538评论 1 2
  • 路边的花儿 静静的绽放 花朵亦灿烂 宁静而唯美 我停下脚步 细细的观赏 陶醉在花中 我尤为欢喜 忘记了前行
    逐梦人生阅读 326评论 0 4
  • 介绍 RabbitMQ是一个由erlang开发的基于AMQP(Advanced Message Queue)协议的...
    SFLYQ阅读 1,111评论 0 9