iOS--把WebView塞進TableView總共分幾步?

  • 前言
  • 讓Webview完全展開
  • 讓WebView自適應
  • 讓裝載WebView的Cell,自適應大小
  • 如何讓一個裝載着WebView的Cell,能夠上拉加載
  • 如果你是伸手黨?

前言

很久不寫東西了,新工作每天忙的不行。這個東西也是做技術調研,感覺還不錯順手搞出的副產品。

列出了幾種html嵌套在原生頁面內的方式。如果正巧你也需要,可以選一個用用。


讓Webview完全展開

最簡便的方式,在HTML高度發生變化之後,令tableView進行reload操作。使用HTML高度設置cell高度。

網上有很多、有需要自己搜一下


需要注意webView加載完成後,高度很可能並未確定,比如圖片加載等操作有機會繼續修改html高度。
所以通過KVO監聽是最穩妥的。


讓WebView自適應

讓WebView具有UILabel的性質,進而撐開cell。達到自適應的目的

在上面提到的kvo監聽方法中,調用invalidateIntrinsicContentSize

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    if (self.loading) {
        return;
    }
    CGFloat height = self.webView.scrollView.contentSize.height;
    if (self.HtmlHeight != height) {
        self.HtmlHeight = height;
        
        //這裏加了一個延時,因爲最開始`height`會頻繁刷新。最後才穩定成最終值
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            if (self.HtmlHeight == height) {
                [self invalidateIntrinsicContentSize];
            }
        });
    }
}

然後在intrinsicContentSize返回控件的內容高度

- (CGSize)intrinsicContentSize {
    return CGSizeMake(self.frame.size.width, self.HtmlHeight);
}

題外話intrinsicContentSize是個好東西,你可以用他,實現一個適應的textView,textField等一切你有辦法確定大小的東西。


讓裝載WebView的Cell,自適應大小

就像使用UILabel一樣添加約束

- (void)setWebViewEdgeInsets:(UIEdgeInsets)webViewEdgeInsets {
    _webViewEdgeInsets = webViewEdgeInsets;
    [self.htmlView mas_remakeConstraints:^(MASConstraintMaker *make) {
        make.edges.equalTo(self.contentView).insets(webViewEdgeInsets);
    }];
}

高度確定之後,讓tableViewReload

//Cell
#pragma mark - KSAdaptiveHtmlViewDelegate
- (void)htmlViewDidFinishLoad:(CGFloat)height {
    if ([self.delegate respondsToSelector:@selector(htmlCellDidFinishLoad:cell:)]) {
        self.HtmlHeight = height;
        [self.delegate htmlCellDidFinishLoad:height cell:self];
    }
}

//ViewController
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    return UITableViewAutomaticDimension;
    
}

#pragma mark KSAdaptiveHTMLCellDelegate
- (void)htmlCellDidFinishLoad:(CGFloat)height cell:(KSAdaptiveHTMLCell *)cell{
    NSLog(@"htmlCellDidFinishLoad");
    [self.tableView reloadData];
}


如何讓一個裝載着WebView的Cell,能夠上拉加載

如果把Cell的高度撐開,與WebView相同,那麼這個WebView將失去上拉加載的功能。
我這裏的處理是將WebView確定在一定的高度(比如和tableView一樣大),然後另其與tableView聯動滑動。

聯動的處理上,參考了HGPersonalCenterExtend。拋開cell的干擾,其實就是scrollView與scrollView的嵌套。

本質上,就是兩個scrollView本身都在響應滑動事件。當一個scrollView不應該滑動時,讓其鎖定在某個位置。

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
    
    CGFloat lockOffset = self.baseScrollSubView.frame.origin.y; //baseScrollView將要被鎖定的偏移量
    if (self.baseScrollView == scrollView) {
        if (self.baseScrollView.contentOffset.y >= lockOffset) { //baseScrollView自己超過了鎖定距離
            self.baseScrollView.contentOffset = CGPointMake(0, lockOffset);
            self.baseViewScroll = NO;
        }else{
            if (!self.baseViewScrolling  && self.subScrollView.contentOffset.y > 0) {//subScrollView正在滾動
                self.baseScrollView.contentOffset = CGPointMake(0, lockOffset);
            }
        }
        self.baseScrollView.showsVerticalScrollIndicator = self.baseViewScrolling?YES:NO;
    }
    if (self.subScrollView == scrollView) {
        if (self.baseScrollView.contentOffset.y != lockOffset) { //如果baseScrollView處在鎖定位置,都要去滾動父ScrollView
            self.baseViewScroll = YES;
        }
        if (self.baseViewScrolling) {
            self.subScrollView.contentOffset = CGPointZero;
        }
        if (self.subScrollView.contentOffset.y <= 0) { //subScrollView到頂後屏蔽下拉動作
            self.subScrollView.contentOffset = CGPointZero;
            self.baseViewScroll = YES;
        }
        self.subScrollView.showsVerticalScrollIndicator = self.baseViewScrolling?NO:YES;
    }
}

如此這般,你就可以讓webView在不充滿的前提下,與tableView聯動了。


如果你是伸手黨?

是的,之所以前面寫的很簡略。是因爲有demo~

順手,我把聯動的邏輯抽了出來,你只要把兩個scrollView丟進去,他們就可以自己聯動的滑起來。


- (void)viewDidLoad {
    [super viewDidLoad];
    [self scrollHelper];
}

- (KSMultistageScrollViewHelper *)scrollHelper {
    if (!_scrollHelper) {
        _scrollHelper = [[KSMultistageScrollViewHelper alloc]initWithBaseScrollView:self.firstScrollView subScrollView:self.secondScrollView];
    }
    return _scrollHelper;
}

DEMO

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章