iOS中webView巢狀tableView中動態高度問題

愛幻想的螃蟹發表於2017-12-20

前言

在開發中,我們可能遇到html網頁的展示需求,為了讓展現內容靈活多變,故很多新聞類的應用都是採用html+本地原生介面進行展示開發的。 從獲取html原始碼開始說起吧!在拿到html原始碼的時候,我們第一步要將這些網頁內容展示到webView上面,顯然,這一步很簡單。如果整個頁面單純的是一個網頁的話,基本就完工了,就是純網頁展示嘛!但是如果是webView嵌入到原生的頁面中,比如將webView嵌入到tableView中,就會遇到一些問題。最不好解決的問題可能就是webView的高度問題了。

方案

webView這個控制元件大家估計都知道,它是有內容高度的,就是contentSize,如果內容高度比控制元件的高度大的話,那麼滾動的時候就是整個webView在滾動,而外層的tablView你會發現似乎沒法接收當前的滾動手勢。這樣其實造成了一個問題,就是本來要瀏覽tableView所要展示的內容,而結果卻成了滾動webView了,是不是很奇怪,這樣會影響使用者體驗。

其實,解決的方法也很簡單,只要將webView的contentSize的高度設定為webView的控制元件高度就可以了。這樣就不會出現webView的內容滾動問題了。關鍵是如何設定這個內容高度,什麼時候設定它比較合適。

其實我嘗試了很多種方案,比如在webView的代理回撥中去實現高度的更新,但是代理中,只有一個webView內容全部載入完成以後的回撥方法,如果在這個時候更新的話,會有很明顯的跳躍效果,真的是很痛苦。因為網頁的內容是實時變化的,如果在網頁載入到最後的時候,在去更新它的高度,這個跳躍會更明顯。而我們所需要的其實就是實時更新網頁內容的高度,只有這樣才能做到像瀏覽網頁一樣瀏覽tablView中的webView。所以為了解決這個問題,我用了kvo,使用kvo監聽網頁內容的高度,如果高度發生變化,就去更新webView的控制元件高度,這樣就做到了實時性,讓網頁的高度與網頁內容的高度始終保持一致,這樣其實就達到了我們期待的效果。

實現

就說說實現吧!程式碼奉上,哈哈~

- (void)creatView{

    self.webView = [[UIWebView alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width, 300)];
    [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com"]]];
    
    //使用kvo為webView新增監聽,監聽webView的內容高度
    [self.webView.scrollView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
    
    self.tableView = [[UITableView alloc]initWithFrame:self.view.frame style:UITableViewStyleGrouped];
    self.tableView.backgroundColor = [UIColor whiteColor];
    self.tableView.delegate = self;
    self.tableView.dataSource = self;
    self.tableView.rowHeight = 80;
    
    //設定webView為tableView的header
    self.tableView.tableHeaderView = self.webView;
    
    [self.view addSubview:self.tableView];
    
    
    

}
複製程式碼
//實時改變webView的控制元件高度,使其高度跟內容高度一致
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{

    if ([keyPath isEqualToString:@"contentSize"]) {
        CGRect frame = self.webView.frame;
        frame.size.height = self.webView.scrollView.contentSize.height;
        self.webView.frame = frame;
        
        self.tableView.tableHeaderView = self.webView;
    }
}

- (void)dealloc{

    //銷燬的時候別忘移除監聽
    [self.webView.scrollView removeObserver:self forKeyPath:@"contentSize"];
}

#pragma -mark- tableView的代理方法
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{

    return 20;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    
    static NSString *cellID = @"reuseCell";
    
    UITableViewCell *tableViewCell = [tableView dequeueReusableCellWithIdentifier:cellID];
    
    if (tableViewCell == nil) {
        tableViewCell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];
    }
    
    
    tableViewCell.textLabel.text = [NSString stringWithFormat:@"%ld",indexPath.row];
    
    return tableViewCell;

    
}

複製程式碼

對應的效果如下:

webView高度demo.gif

例子

點我看 Demo

相關文章