directory

Do content display page, often use the WKWebView+UITableView mixed function, now do a summary, the function of the implementation I used four methods.

  • 1, tableView. TableHeaderView = webView maintains the webView
  • [webView.scrollView addSubview:tableView] + placeholder Div
  • 3, tableView. TableHeaderView = the webView doesn’t open the webView (recommended)
  • ScrollView addSubView: webView & tableView (recommended)
  • 5, the end

Plan 1:

WebView, as the Header of tableView, supports webView to display and render all content. When the content is too much, such as a large number of hd pictures, it is easy to cause memory explosion (not recommended). This scheme is simple and crude, and only applies to scenes with little content.

Scheme 2:

Simple book content page implementation scheme: UIWebView and UITableView nesting scheme

Add the tableView to webView.scrollView, and the HTML loaded by the webView leaves a blank placeholder div at the end to determine the tableView’s location. In listening to a webView. ScrollView. After the contentSize changes, constantly adjust the position of the tableView and sets the size of the div to the size of the tableView. Disable scrollEnabled = NO for tableView and webView.scrollVie, and manually adjust contentOffset by adding pan gestures. The maximum height of a tableView is the screen height. If the content is less than one screen, the height is the content height.

Option 3(Recommended) :

The webView is the Header of the tableView, but it doesn’t support the webView. Disable scrollEnabled = NO for tableView and webView.scrollVie, and manually adjust contentOffset by adding pan gestures. The maximum height of a webView is the screen height. If the content is less than one screen, the height is the content height. Similar to scenario 2, but without inserting placeholder divs. The main code is as follows:

  • Step 1: Initialize the configuration
/ / disable comes _webView. The features of the sliding scrollView. ScrollEnabled = NO; _tableView.scrollEnabled = NO; / / add drag to parent view [self. View addGestureRecognizer: self. PanRecognizer];Copy the code
  • Step 2: Manually adjust contentOffset
// drag gesture, Analog UIScrollView sliding - (void) handlePanGestureRecognizer: (UIPanGestureRecognizer *) recognizer {switch (recognizer. State) { Case UIGestureRecognizerStateBegan: {/ / drag, before removing all the dynamic behavior of [self. DynamicAnimator removeAllBehaviors]; } break; case UIGestureRecognizerStateChanged: { CGPoint translation = [recognizer translationInView:self.view]; / / drag in the process of adjusting scrollView. ContentOffset [self scrollViewsSetContentOffsetY: translation. The y]; [recognizer setTranslation:CGPointZero inView:self.view]; } break; case UIGestureRecognizerStateEnded: {// This if is used to avoid pulling to the edge, Recognizer velocityInView:self.view].y) < 120) {if ([self.tableView sl_isTop] && [self. WebView. ScrollView sl_isTop]) {/ / top [self performBounceForScrollView: self. WebView. The scrollView isAtTop: YES]; } else if ([self.tableView sl_isBottom] && [self.webView.scrollView sl_isBottom]) {// Bottom if (self. TableView. Frame. The size. Height < self. View. Sl_height) {/ / tableView less than one screen, webView bounce [self performBounceForScrollView:self.webView.scrollView isAtTop:NO]; } else { [self performBounceForScrollView:self.tableView isAtTop:NO]; } } return; }Copy the code
  • Step 3: Simulate inertia and edge rebound effects
// SLDynamicItem *item = [[SLDynamicItem alloc] init]; item.center = CGPointZero; __block CGFloat lastCenterY = 0; // UIDynamicItemBehavior *inertialBehavior = [[UIDynamicItemBehavior alloc] initWithItems:@[item]]; / / add the initial linear velocity to the item The speed of the fingers when [inertialBehavior addLinearVelocity: CGPointMake (0, -[recognizer velocityInView:self.view].y) forItem:item]; / / deceleration speed without damping inertialBehavior. Hold = 2; __weak typeof(self) weakSelf = self; InertialBehavior. Action = ^ {/ / inertial force moving distance [weakSelf scrollViewsSetContentOffsetY: lastCenterY - item. Center. The y]; lastCenterY = item.center.y; }; // Note that the modifier self.inertialBehavior is weak, and when the inertia force stops, the inertialBehavior object is released, self.inertialBehavior = nil self.inertialBehavior = inertialBehavior; [self.dynamicAnimator addBehavior:inertialBehavior]; } / / rebound - (void) performBounceForScrollView: (UIScrollView *) scrollView isAtTop: (BOOL) isTop {the if (! Self. BounceBehavior) {/ / remove the inertial force [self. DynamicAnimator removeBehavior: self. InertialBehavior]; // SLDynamicItem *item = [[SLDynamicItem alloc] init]; item.center = scrollView.contentOffset; Y CGFloat attachedToAnchorY = 0; AttachedToAnchorY = isTop? If (scrollView == self.tableView) {attachedToAnchorY = isTop? 0 : [self.tableView sl_maxContentOffsetY]; }else { attachedToAnchorY = 0; } UIAttachmentBehavior *bounceBehavior = [[UIAttachmentBehavior alloc] initWithItem:item attachedToAnchor:CGPointMake(0, attachedToAnchorY)]; Bouncebehavior. length = 0; // damping/buffer. Damping = 1; BounceBehavior. Frequency = 2; bounceBehavior.action = ^{ scrollView.contentOffset = CGPointMake(0, item.center.y); }; self.bounceBehavior = bounceBehavior; [self.dynamicAnimator addBehavior:bounceBehavior]; }}Copy the code

Options 2 and 3 rely on the dynamics/simulation physics module in UIKit to achieve inertial sliding and edge rebound effects after release. The classes involved mainly include UIDynamicAnimator, UIDynamicItemBehavior, UIAttachmentBehavior, and UIDynamicItem. I also use these classes to customize classes that inherit from UIView to achieve the effect of UIScrollView, see the code for details.

Option 4(Recommended) :

[scrollView addSubView: webView & tableView]; scrollView.contenSize = webView.contenSize + tableView.contenSize; The maximum webView and tableView height is one screen high and scrollEnabled=NO is disabled. Then adjust the presentation area of webView and tableView contenOffset according to the sliding offset of scrollView.

  • Step 1: Determine the height of webView and tableView
// addObserver to listen webView and tableView contentSize - (void)addKVO{[self.webView addObserver:self forKeyPath:NSStringFromSelector(@selector(estimatedProgress)) options:NSKeyValueObservingOptionNew context:nil]; [self.webView addObserver:self forKeyPath:@"scrollView.contentSize" options:NSKeyValueObservingOptionNew context:nil]; [self.tableView addObserver:self forKeyPath:@"contentSize" options:NSKeyValueObservingOptionNew context:nil]; } // use WebView and tableView ContentSize. Adjust the father scrollView. ContentSize, WebView and the height of the tableView position, display area - (void) updateContainerScrollViewContentSize { self.containerScrollView.contentSize = CGSizeMake(self.view.sl_width, _webViewContentHeight + _tableViewContentHeight); // If the content is less than one screen, then the height of webView and tableView is the content high, CGFloat webViewHeight = (_webViewContentHeight < self_view.sl_height)? _webViewContentHeight : self.view.sl_height ; CGFloat tableViewHeight = _tableViewContentHeight < self.view.sl_height ? _tableViewContentHeight : self.view.sl_height; self.contentView.sl_height = webViewHeight + tableViewHeight; Self.webview. sl_height = webViewHeight <= 0.1? 0.1: webViewHeight; self.tableView.sl_height = tableViewHeight; self.tableView.sl_y = self.webView.sl_height; / / update display area [self scrollViewDidScroll: self. ContainerScrollView]; }Copy the code
  • Step 2: Adjust the position and offset of webView and tableView according to the offset of scrollView
#pragma mark - UIScrollViewDelegate - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ if (_containerScrollView ! = scrollView) { return; } CGFloat offsetY = scrollView.contentOffset.y; CGFloat webViewHeight = self.webView.sl_height; CGFloat tableViewHeight = self.tableView.sl_height; If (offsetY <= 0) {// Pull down self.contentView.sl_y = 0; self.webView.scrollView.contentOffset = CGPointZero; self.tableView.contentOffset = CGPointZero; }else if(offsetY < _webViewContentHeight - webViewHeight){// The parent scrollView offset is displayed in the webView's maximum offset content area ContentView. Sl_y = offsetY; // contentOffset self.contentView.sl_y = offsetY; self.webView.scrollView.contentOffset = CGPointMake(0, offsetY); self.tableView.contentOffset = CGPointZero; }else if(offsetY < _webViewContentHeight){self.contentView.sl_y = _webViewContentHeight - webViewHeight;  self.webView.scrollView.contentOffset = CGPointMake(0, _webViewContentHeight - webViewHeight); self.tableView.contentOffset = CGPointZero; }else if(offsetY < _webViewContentHeight + _tableViewContentHeight - tableViewHeight){ // Adjust the contentOffset self.contentView.sl_y = offsetY - webViewHeight; // Adjust the contentOffset self.contentView.sl_y = offsetY - webViewHeight; self.tableView.contentOffset = CGPointMake(0, offsetY - _webViewContentHeight); self.webView.scrollView.contentOffset = CGPointMake(0, _webViewContentHeight - webViewHeight); }else if(offsetY <= _webViewContentHeight + _tableViewContentHeight){self.contentView.sl_y = self.containerScrollView.contentSize.height - self.contentView.sl_height; self.webView.scrollView.contentOffset = CGPointMake(0, _webViewContentHeight - webViewHeight); self.tableView.contentOffset = CGPointMake(0, _tableViewContentHeight - tableViewHeight); }else { } }Copy the code

5, the end

WKWebView, WKWebView+UITableView mix, UIScrollView implementation principle, WKWebView offline cache function and more content are at github.com/wsl2ls/iOS_…

IOS_Tips Collection Introduction: Dark mode 2. AppleID login application 3. AVFoundation High imitation wechat camera shooting and editing 4. AVFoundation face detection 5 7, VideoToolBox and AudioToolBox audio and video codec 8, OpenGL ES learning 9, LeetCode algorithm practice 10, the coexistence of keyboard and UIMenuController 11, iOS Crash protection 12, WKWebView