iOS開發(fā)WKWebView計算內(nèi)容高度2018-08-02

一,先計算WebView的內(nèi)容高度

1,想當然的方法1

既然想計算webView中網(wǎng)頁的高度,那就在網(wǎng)頁加載完成的時候,直接返回
scrollView.contentSize.height。

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

這個結(jié)果返回值:是0。
為啥不行,這里面先理解成這里的加載完成只是網(wǎng)頁請求解析完成,還沒有放在WebView的scrollView上顯示!

2,一般方法

一般我們計算webView的高度,網(wǎng)上有栗子是通過調(diào)用網(wǎng)頁的方法來實現(xiàn),如下:

#pragma mark - WKNavigationDelegate
// 頁面加載完成之后調(diào)用
- (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內(nèi)容高度計算[18606:6890472] scrollHeight高度:5497.00
2016-11-08 11:41:50.574534 WebView內(nèi)容高度計算[18606:6890472] offsetHeight高度:5465.00

通過調(diào)用html的body標簽的屬性,我們?nèi)ゴ_實可以獲取高度,這里分別用了:scrollHeightoffsetHeight。如果想要計算webView上scrollView的contentSize的height 那么用scrollHeight這個計算還是挺準確的,這個offsetHeight計算的會查幾十個高度(網(wǎng)頁不同差的不同,這個原因我不知道)。

但是,這只是一般方法,只能說如果你的web頁面是你們的H5工程師給你們寫的(其實特指頁面不能縮放的),那是可以的,沒問題。如果你的頁面是順便一個網(wǎng)頁,比如oschina主頁https://www.oschina.net,這會你計算,這個方法返回的值和你scrollView真正能滾動的區(qū)域就差很遠了!

為什么了?
因為我們的WKWebView會根據(jù)網(wǎng)頁的大小來自動縮放網(wǎng)頁(UIWebView可以通過設(shè)置scalesPageToFit來開啟),而這個方法計算的是縮放前的網(wǎng)頁滾動區(qū)域大小,所以我們?nèi)绻胗嬎愠隹s放后的高度,就要算出縮放比,然后乘上這個縮放比。關(guān)鍵是這個縮放比怎么拿?UIWebView我們沒有直接屬性可拿這個縮放比,而WKWebView有magnification屬性但是phone不可用??,我們可以算出寬度,再根據(jù)webView的寬度算出,下面是代碼

#pragma mark - WKNavigationDelegate

// 頁面加載完成之后調(diào)用
- (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,監(jiān)聽scrollView.contentSize

[self.wbScrollView addObserver:self forKeyPath:@"contentSize" 
options:NSKeyValueObservingOptionNew context:nil];
#pragma mark  - KVO回調(diào)
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    //更具內(nèi)容的高重置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內(nèi)容高度計算[19613:7236291] Height is changed! new=NSSize: {998, 2740}
2016-11-09 17:28:25.850227 WebView內(nèi)容高度計算[19613:7236291] tianxia :{998, 2740}
2016-11-09 17:28:25.850916 WebView內(nèi)容高度計算[19613:7236291] Height is changed! new=NSSize: {320, 878.5}
2016-11-09 17:28:25.850987 WebView內(nèi)容高度計算[19613:7236291] tianxia :{320, 878.5}
2016-11-09 17:28:25.927509 WebView內(nèi)容高度計算[19613:7236291] Height is changed! new=NSSize: {320, 878.5}
2016-11-09 17:28:25.927660 WebView內(nèi)容高度計算[19613:7236291] tianxia :{320, 878.5}
2016-11-09 17:28:25.927836 WebView內(nèi)容高度計算[19613:7236291] Height is changed! new=NSSize: {320, 878.5}

第一次計算出的2740就是通過方法2不乘以縮放比得到的值!

二,下方放入TableView做評論列表

1,解決webView 和 table滾動的協(xié)調(diào)性

思路就是,把WebView作為TableView的TableHeader。這里我們控制WebView最高也就是屏幕的高,如果內(nèi)容大于WebView的高度(所以有了上面計算webView的內(nèi)容高度),需要滾動顯示W(wǎng)ebView的內(nèi)容,直到滾動到最底端的時候,才滾動出tableView!
初始狀態(tài)控制:
初始狀態(tài)我們需要把webView的scrollView的回彈bounces一直禁止掉,防止和TableView的回彈沖突。

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

我們只需要監(jiān)聽tableView的滾動事件,在他的偏移度為<<=0的時候,我們要讓webView的scrollVIew可以滾動,同時關(guān)閉tableView的回彈bounces,在table的偏移度>0的時候,就取反,這樣我們可以控制webView和table滾動的協(xié)調(diào)性。

#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,解決網(wǎng)頁動態(tài)加載內(nèi)容高度變化問題

網(wǎng)頁加載的時候在加載完成會調(diào)用webView 的delegate ,這時候我們可以計算出網(wǎng)頁的高度,重置我的webView的frame 的高(使用方法2),但是我們可能會忽視一個問題,如果網(wǎng)頁中有圖片的話,因為圖片大多數(shù)都是異步加載的,在webView加載完成的時候計算出的內(nèi)容高度并不包含圖片的高度,所以我們要設(shè)置一個監(jiān)聽KVO,來監(jiān)聽內(nèi)容高度的變化!

#pragma mark - WKNavigationDelegate

// 頁面加載完成之后調(diào)用
- (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監(jiān)聽網(wǎng)頁內(nèi)容高度變化
            if (newHeight < CGRectGetHeight(self.view.frame)) {
                //如果webView此時還不是滿屏,就需要監(jiān)聽webView的變化  添加監(jiān)聽來動態(tài)監(jiān)聽內(nèi)容視圖的滾動區(qū)域大小
                [self.wbScrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil];
            }
        }];
        
    }];
}

在監(jiān)聽回調(diào)中,重置(Reset) webView的frame。

#pragma mark  - KVO回調(diào)
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
    
    //更具內(nèi)容的高重置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,發(fā)現(xiàn)在控制滾動沖突上不是多理想

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、通過CocoaPods安裝項目名稱項目信息 AFNetworking網(wǎng)絡(luò)請求組件 FMDB本地數(shù)據(jù)庫組件 SD...
    陽明AI閱讀 16,172評論 3 119
  • 有人調(diào)侃我最近寫的都是理財,對理財不感冒到開賣理財險,開始算計了,戰(zhàn)場有變化。我在此做個解釋。 ...
    一團泥巴閱讀 308評論 0 0
  • 我一直謙卑隱忍地跟隨在長輩身后,時不時表現(xiàn)出恰到好處的附和恭維。掌握拳柄的人認為:只要沒有人指出,他就永遠不容置疑...
    scholarismart閱讀 572評論 1 2
  • 路邊的花兒 靜靜的綻放 花朵亦燦爛 寧靜而唯美 我停下腳步 細細的觀賞 陶醉在花中 我尤為歡喜 忘記了前行
    逐夢人生閱讀 365評論 0 4
  • 介紹 RabbitMQ是一個由erlang開發(fā)的基于AMQP(Advanced Message Queue)協(xié)議的...
    SFLYQ閱讀 1,134評論 0 9

友情鏈接更多精彩內(nèi)容