- 前言
- 讓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;
}