標籤: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\" />
這段代碼 注入在載入的時候
例如:
- (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]]]; } }}
注意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";
這是代理方法裡面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返回高度
那麼這個時候 你還會發現,滾動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]; } }}
你需要加上這個代碼.
嗯這時候,H5和原生就完美的無縫串連了.
這些東西也並非我一個人獨立想出來的,在這裡也對我的好朋友–徐陽 表示由衷的感謝,是他給我提供了很多思路.對,就是上面我推薦文章的那個人.
還不知道下一篇想寫什麼,最近忽然又對寫部落格起了興趣.
iOS 【野路子】擷取WKWebView內容高度做H5原生串連