iOS 【野路子】擷取WKWebView內容高度做H5原生串連

來源:互聯網
上載者:User

標籤:load   sel   ati      sla   base   java   朋友   err   

前言:是這樣的,剛寫完上一篇文章還沒緩過神來,上一篇文章我還提到了,想和大家聊聊原生+H5如何無縫串連的故事.結果我朋友就給我發了兩篇他的作品.他的做法也都有獨到之處.好的文章都是這樣,讓你每次看都能有新的收穫,我們也都致力於寫一些能幫別人解決問題的文章,下面我用另一種方式來完美實現這個問題.畢竟之前大家都是根據UIWebView寫的,我來說說換成WK之後的區別,主題思路也不同哦~ 
插兩個連結,是我朋友的大家也可以做個對比

iOS 【終極方案】精準擷取webView內容高度,自適應高度 
iOS 【奇巧淫技】擷取webView內容高度 
iOS WKWebView 圖片點擊放大並左右滑動,類似/網易文章功能

首先先說應用情境吧,這樣大家可能更能接受一點

例1:一個頁面 分為上下兩個部分,上部分為文章,商品圖文介紹等(H5)一個web,下半部分是原生的列表(tableView) 
那麼怎麼把H5和原生結合在一起呢,最簡單的思想就是把H5做成表頭,對吧.那麼擷取Web部分的真實高度就是最大的痛點公關.

例2:上面是一個原生介紹,下面分為3部分,其中一部分是H5頁面的詳情介紹,一部分是評論列表,一部分是相關推薦等等,這樣,最合理的結構就是:上面作為一個Tabview的表頭,下面共用同一個tabview,將H5的web嵌入成某一種tableviewCell當中.那麼痛點就是怎麼擷取Web這個cell的高度返回.

我就拿第二種來舉例子吧.畢竟第二種更複雜一些,而且例1 很多工程都實現了,我朋友的文章也能實現這個功能,第二種例子,我用WKWebView給大家提供一個新的思路.

嗶嗶叨叨了這麼多,下面開始說正題吧.

首先跟大家說一下,簡單的擷取contentSize 什麼的(網上一搜隨處可見的那幾個方法)我就不吐槽了,他們的應用情境太局限了,稍微在進行富文本編輯的時候 插入的圖片 尺寸 或者某些動圖之類的 都會導致你擷取的高度不準,然後介面UI噁心到不行. 
那麼思路依舊是跟我上一篇文章一樣 利用JS注入來解決 
首先從載入的時候開始 
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier 

self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 
if(self){ 
self.contentView.backgroundColor = NineColorOne; 
[self creatSubviews]; 

return self; 

- (void)creatSubviews 

WKWebViewConfiguration *confifg = [[WKWebViewConfiguration alloc] init]; 
confifg.selectionGranularity = WKSelectionGranularityCharacter; 
_webView = [[WKWebView alloc] initWithFrame:CGRectMake(14, 0, CurrentScreenWidth - 28, 1) configuration:confifg]; 
self.contentView.backgroundColor = NineColorOne; 
// _webView.scalesPageToFit = NO; 
_webView.scrollView.scrollEnabled=NO; 
_webView.userInteractionEnabled = NO; 
_webView.opaque = NO; 
_webView.scrollView.bounces=NO; 
_webView.backgroundColor=NineColorOne; 
_webView.scrollView.decelerationRate=UIScrollViewDecelerationRateNormal; 
[self.contentView addSubview:_webView]; 
}
 
我剛才說了,把web放在一個cell裡,那麼它的代理就要在VC裡面去簽. 
大家注意到,_webView.scalesPageToFit = NO;這句話我屏蔽掉了,因為WKWebView是沒有這個屬性的 它和UIWebView不同,然而 如果不設定NO, WKWebView的預設效果和UIWebView.scalesPageToFit = YES是一樣的,這時候,你需要這段代碼:

<meta content=\"width=device-width, initial-scale=1.0, maximum-scale=3.0, user-scalable=0;\" name=\"viewport\" />
  • 1

這段代碼 注入在載入的時候 
例如:

- (void)setDetail:(NSString *)detail{        if(!_detail){                _detail = detail;            if (_detail.length >0) {                [_webView loadHTMLString:[NSString stringWithFormat:@"<meta content=\"width=device-width, initial-scale=1.0, maximum-scale=3.0, user-scalable=0;\" name=\"viewport\" />%@<div id=\"testDiv\" style = \"height:100px; width:100px\"></div>",_detail] baseURL:[NSURL fileURLWithPath: [[NSBundle mainBundle]  bundlePath]]];                }        }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

注意2點: 
1.因為整體邏輯是 Web放在cell裡,載入完成後重新整理tabview,那麼重新整理的時候 走代理方法cellforrow,則cell會重新賦值,產生死鏈.所以在賦值時候要做基本處理 
2.我在注入scalesPageToFit代碼的同時,似乎還加了一個div?對的,你沒有看錯.下面我就說一說,這個div是幹什麼用的

我們將目光切回到VC

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath         _webview = cell.webView;        cell.webView.navigationDelegate = self;        cell.webView.UIDelegate = self;        cell.selectionStyle = 0;        cell.detail = @"這裡就是你要載入的html";
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

這是代理方法裡面cell的部分代碼.可以看到 代理我們都簽在了VC裡 
緊接著看載入完成方法

- (void)webView:(WKWebView *)webView didFinishNavigation:(null_unspecified WKNavigation *)navigation{    [webView evaluateJavaScript:@"document.getElementById(\"testDiv\").offsetTop"completionHandler:^(id _Nullable result,NSError * _Nullable error) {        //擷取頁面高度,並重設webview的frame        CGFloat lastHeight  = [result doubleValue];        webView.frame = CGRectMake(14, 0, CurrentScreenWidth - 28, lastHeight);        webHeight = lastHeight;        [self.tableView beginUpdates];        [self.tableView endUpdates];    }];}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

注意看一下這裡,首先WK的JS注入方法有變化,其次就是你發現我取web的高度利用了我剛才在載入HTML時注入的div塊 
這樣,不管你的網頁是什麼樣的,在尾部加一個div它的位置永遠是你需要的高度.(一定要注意這段代碼不加的話 擷取的高度同樣不準哦)

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{    if(_type == 0){        return webHeight;        }// 當前tableview是載入web狀態時 cell返回高度
  • 1
  • 2
  • 3
  • 4
  • 5

那麼這個時候 你還會發現,滾動tableView時,web顯示內容沒有變化!!! 
對,這就是WKWebView的另一個區別,由於WKWebView採用的lazy載入模式,所在的scrollView的滾動被禁用,導致被嵌套的WKCompositingView不進行資料載入。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {    // 判斷webView所在的cell是否可見,如果可見就layout    NSArray *cells = self.tableView.visibleCells;    for (UITableViewCell *cell in cells) {        if ([cell isKindOfClass:[UITableViewCell class]]) {            UITableViewCell *webCell = (UITableViewCell *)cell;            [webCell.webView setNeedsLayout];        }    }}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

你需要加上這個代碼.

嗯這時候,H5和原生就完美的無縫串連了. 
這些東西也並非我一個人獨立想出來的,在這裡也對我的好朋友–徐陽 表示由衷的感謝,是他給我提供了很多思路.對,就是上面我推薦文章的那個人.

還不知道下一篇想寫什麼,最近忽然又對寫部落格起了興趣.

iOS 【野路子】擷取WKWebView內容高度做H5原生串連

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.