美文网首页Swift&Objective-C
wkWebView有headerView和footerView并

wkWebView有headerView和footerView并

作者: 布袋的世界 | 来源:发表于2017-09-30 11:16 被阅读594次

    每次发简书都是自己遇到的坑,填平后分享给大家,希望后来者可以少遇到些坑,
    发代码前,首先很感谢二位简书的小伙伴给的帮助:

    一、螃蟹(http://www.jianshu.com/u/82961c9b9e78) 提供的idea,在 webView的头部和底部分别加上一个view及KVO的思想;
    二、杨Hrscy (http://www.jianshu.com/u/c0a496a1c168)提供的controller 导入xib的代码及帮助;

    tableView的头部直接加 webView是很简单的,难点在于如何:

    1、又在 tableView的tableHeaderView上的webView多加上一个顶部还有一个尾部view,因为webView的高度不确定性,加在webView底部的footerView要等计算出webView的实际高度后再加入
    2、webView得用webView.scrollView.contentInset = UIEdgeInsetsMake(80, 0, 160, 0)偏移出相应的高度,并利用多出来的空间加上相应的headerView和footerView

    以上这些问题详见代码,先见图然后看代码

    webView1.png webView2.png webView3.png webView4.png webView8.png webView9.png webView10.png

    上代码了!

    //  HomeDetailController.swift
    //  Created by Apiapia on 2017/9/30.
    //  Copyright © 2017年 www.elinknet.cn All rights reserved.
    //  view 作为 tableView 的 tableHeaderView,单纯的改变 view 的 frame 是无济于事的 tableView不会大度到时刻适应它的高度
    
    import UIKit
    import WebKit
    import RxSwift
    import RxCocoa
    import MJRefresh
    import SVProgressHUD
    import Kingfisher
    import IBAnimatable
    import IQKeyboardManager
    
    class WeiTouTiaoDetailController: UIViewController,WKUIDelegate,WKNavigationDelegate {
        
        fileprivate let disposeBag = DisposeBag()    // RX
        fileprivate var commentValue :Int = 0 // 评论数量
        fileprivate var content:String = ""
        @IBOutlet weak var tableView: UITableView!
        var comments = [NewsDetailImageComment]() // 评论列表
        var imgStr = ""
        var htmlString: String = ""
        var weitoutiao: WeiTouTiao? { //FIXME: user ,user_info,mediao_info 三种待统一
            didSet {
                if let content = weitoutiao!.content {
                    self.content = content as String 
                }
                weitoutiao?.large_image_list.forEach({ (image) in
                    imgStr += "<img src=\"\(String(describing: image.url!))\">"
                })
                commentValue = (weitoutiao?.comment_count)! // 评论数量
                if let user = weitoutiao!.user {
                    navView.usernameLabel.text = user.name
                    navView.avatarImageView.kf.setImage(with: URL(string: user.avatar_url!))
                } else if let userInfo = weitoutiao!.user_info {
                    navView.usernameLabel.text = userInfo.name
                    navView.avatarImageView.kf.setImage(with: URL(string: userInfo.avatar_url!))
                } else if let mediaInfo = weitoutiao!.media_info {
                    navView.usernameLabel.text = mediaInfo.name
                    navView.avatarImageView.kf.setImage(with: URL(string: mediaInfo.avatar_url!))
                }
                /// 设置headerView属性
                webViewHeaderView.weitoutiao = weitoutiao!
                /// 获取评论
                NetworkTool.loadNewsDetailComments(offset: 0, weitoutiao: weitoutiao!) { (comments) in
                    self.comments = comments
                    self.tableView.reloadData()
                }
            }
        }
        
        fileprivate lazy var navView: ConcernNavigationView = {
            let navView = ConcernNavigationView.concernNavView()
            navView.returnButton.setImage(UIImage(named: "leftbackicon_white_titlebar_24x24_"), for: .normal)
            navView.bottomLine.isHidden = false // 显示分割线
            navView.backgroundColor = UIColor.globalRedColor()
            navView.delegate = self
            navView.vipImageView.isHidden = false
            navView.avatarImageView.isHidden = false
            navView.usernameLabel.isHidden = false
            if let userVerified = self.weitoutiao!.user_verified {
                navView.vipImageView.isHidden = !userVerified
            }
            return navView
        }()
        /// 微头条详情页 头部
        fileprivate lazy var webViewHeaderView: NewsDetailHeaderView = {
            let headerView = NewsDetailHeaderView.headerView()
            headerView.frame = CGRect(x: 0, y: -80, width: screenWidth, height: 80)
            return headerView
        }()
        
        fileprivate lazy var webViewHeaderViewBak: UIView = {
            let headerView = UIView.init()
            headerView.frame = CGRect(x: 0, y: -80, width: screenWidth, height: 80)
            headerView.backgroundColor = UIColor.yellow
            return headerView
        }()
        
        fileprivate lazy var webViewFooterView:WebViewFooterView = {
            let footerView = WebViewFooterView.footerView()
            footerView.frame.size.height = 160
            return footerView
        }()
        
        fileprivate lazy var webViewFooterViewBak: UIView = {
            let footerView = UIView.init()
            footerView.frame.size.height = 160
            footerView.backgroundColor = UIColor.red
            return footerView
        }()
        
        fileprivate lazy var webView: WKWebView = {
            let webView = WKWebView.init()
            webView.frame = CGRect(x: 0, y: 0, width: screenWidth, height: screenHeight)
            webView.scrollView.contentInset = UIEdgeInsetsMake(80, 0, 160, 0)
            webView.uiDelegate = self
            webView.navigationDelegate = self
            webView.scrollView.isScrollEnabled = false // 设置不能滚动
            return webView
        }()
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
            // 设置状态栏属性
            navigationController?.navigationBar.barStyle = .black
            navigationController?.setNavigationBarHidden(true, animated: animated)  // 导航条Hidden
            //navigationController?.setUpGlobalPan() // 开启全局手势
            setupUI()
        }
        
        override func viewWillDisappear(_ animated: Bool) {
            super.viewWillDisappear(animated)
            navigationController?.setNavigationBarHidden(false, animated: animated)
            //navigationController?.removeGlobalPanGes() // 清除全局手势
        }
        override func viewDidLoad() {
            super.viewDidLoad()
            IQKeyboardManager.shared().isEnabled = false //MARK:- 这个库时不时会有小BUG...禁用
            htmlString  += "<html>"
            htmlString  += "<head>"
            htmlString  += "<meta name=\"viewport\" content=\"width=device-width,initial-scale=1,user-scalable=0\">"
            htmlString  += "<style>img{width:99%;margin:5;}body,html{margin:5;padding:5;border:0;}</style>"
            htmlString  += "</head>"
            htmlString  += "<body>"
            htmlString  += "\(self.content)<br>"
            htmlString  += "\(imgStr)"
            htmlString  += "</body>"
            htmlString  += "</html>"
            printLog(htmlString)
            webView.loadHTMLString(htmlString, baseURL: Bundle.main.bundleURL)
            //使用kvo为webView添加监听,监听webView的内容高度
            webView.scrollView.addObserver(self, forKeyPath: "contentSize", options: [.old,.new], context: nil)
            webView.scrollView.addSubview(webViewHeaderView)
            //webView.scrollView.addSubview(webViewFooterView) // 底部
            self.tableView.tableHeaderView = webView
            tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        }
        deinit {
            self.webView.scrollView.removeObserver(self, forKeyPath: "contentSize")
        }
        
    }
    //MARK: - 表格代理 ##################################
    extension WeiTouTiaoDetailController: UITableViewDelegate, UITableViewDataSource {
        /// cell 的高度
        func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    //        let comment = comments[indexPath.row]
    //        return comment.cellHeight!
            return 50 
            
        }
        
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return   comments.count != 0 ? comments.count : 10
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            /*let comment = comments[indexPath.row]
            let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: NewsDetailImageCommentCell.self), for: indexPath) as! NewsDetailImageCommentCell
            /// 判断评论是不是作者
            if let user = weitoutiao!.user {
                if comment.user_id! == user.user_id! {
                    cell.isAuthor = true
                }
            } else if let userInfo = weitoutiao!.user_info {
                if comment.user_id! == userInfo.user_id! {
                    cell.isAuthor = true
                }
            } else if let mediaInfo = weitoutiao!.media_info {
                if comment.user_id! == mediaInfo.user_id! {
                    cell.isAuthor = true
                }
            }
            cell.comment = comments[indexPath.row]
            cellClickedEvent(cell: cell)
            */
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
            cell.textLabel?.text = String(indexPath.row+1)
            return cell
        }
        /// 设置 present 出来的控制器
        private func setupPresentationController(cell: NewsDetailImageCommentCell) {
            let followDetailVC = FollowDetailViewController()
            followDetailVC.userid = cell.comment!.user_id!
            followDetailVC.dismissalAnimationType = .cover(from: .right)
            followDetailVC.presentationAnimationType = .cover(from: .right)
            followDetailVC.modalSize = (width: .full, height: .full)
            self.present(followDetailVC, animated: true, completion: nil)
        }
        
        /// cell 按钮点击事件
        private func cellClickedEvent(cell: NewsDetailImageCommentCell) {
            // 头像按钮点击
            cell.avatarButton.rx.controlEvent(.touchUpInside)
                .subscribe(onNext: { [weak self] in
                    self!.setupPresentationController(cell: cell)
                })
                .addDisposableTo(disposeBag)
            // 用户名点击
            cell.nameLabel.rx.controlEvent(.touchUpInside)
                .subscribe(onNext: { [weak self] in
                    self!.setupPresentationController(cell: cell)
                })
                .addDisposableTo(disposeBag)
            // 点击了 评论内容或者回复
            cell.coverReplayButton.rx.controlEvent(.touchUpInside)
                .subscribe(onNext: {
                    
                })
                .addDisposableTo(disposeBag)
        }
    }
    
    extension WeiTouTiaoDetailController {
        
        func setupUI() {
            automaticallyAdjustsScrollViewInsets = false
            tableView.delegate = self
            tableView.dataSource = self
            view.addSubview(navView)
        }
    }
    //MARK: - webView代理 实时观察HTML的高度  ##############
    extension WeiTouTiaoDetailController {
        
        func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
            webView.evaluateJavaScript("document.body.offsetHeight;") { (result, error) in
                var frame:CGRect = webView.frame
                frame.size.height = result as! CGFloat
                frame.size.height += self.webViewHeaderView.frame.size.height //顶部
                frame.size.height += self.webViewFooterView.frame.size.height //底部
                webView.frame = frame
                self.webView.scrollView.addSubview(self.webViewFooterView) // 加载完毕后再加载
                self.webViewFooterView.frame =
                    CGRect(x: 0,
                           y: webView.frame.maxY-self.webViewHeaderView.frame.size.height-self.webViewFooterView.frame.size.height,
                           width: screenWidth,
                           height: 160)
                self.tableView.tableHeaderView = webView
            }
            
        }
    }
    
    // MARK: - webView KVO 实时改变webView的控件高度,使其高度跟内容高度一致 
    extension WeiTouTiaoDetailController {
        
        override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
            if (keyPath == "contentSize") {
    // 加延迟以保证获得的高度包含偏移的部份
                DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(0.1 * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: {() -> Void in
                     var frame: CGRect = self.webView.frame
                     frame.size.height = self.webView.scrollView.contentSize.height //webView loadHtml加载后的内容高度
                     //self.webView.frame = CGRect(x: 0, y: 0, width: screenWidth, height: self.webView.scrollView.contentSize.height)
                     self.webView.frame = frame
                     self.tableView.tableHeaderView = self.webView
                })
                
            
            }
        }
    }
    // MARK: - 代理回调 Mine我的 / ConcernNavigationViewDelegate
    extension WeiTouTiaoDetailController: ConcernNavigationViewDelegate {
        /// 返回按钮点击
        func concernHeaderViewReturnButtonClicked() {
            if (navigationController != nil) {
                navigationController?.popViewController(animated: true)
            } else {
                dismiss(animated: true, completion: nil)
            }
        }
        /// 更多按钮点击
        func concernHeaderViewMoreButtonClicked() {
            
            let userVC = FollowDetailViewController()
            if let user = weitoutiao?.user {
                userVC.userid = user.user_id!
            } else if let user_info = weitoutiao?.user_info {
                userVC.userid = user_info.user_id!
            }
            navigationController?.pushViewController(userVC, animated: true)
        }
        func concernHeaderUsernameButtonClicked() {
            
            let userVC = FollowDetailViewController()
            if let user = weitoutiao?.user {
                userVC.userid = user.user_id!
            } else if let user_info = weitoutiao?.user_info {
                userVC.userid = user_info.user_id!
            }
            navigationController?.pushViewController(userVC, animated: true)
            
        }
    }
    
    //MARK: -  修改状态条颜色 没有导航条的情况下 会执行 否则执行 navBar.barStyle = .black
    extension WeiTouTiaoDetailController {
        override var preferredStatusBarStyle: UIStatusBarStyle {
            return .lightContent
        }
    }
    
    

    哈,就这些了,网上确实有很多针对webView如何加view这个的问题,但总觉得太过于分散,而且有的给的代码存在有不少的坑,觉得自己很有必要把填平完的坑分享给后来者,希望大家喜欢!

    还有自己代码水平有限,希望大家多多见谅,再次感谢您浏览!

    相关文章

      网友评论

      • 李W:博主在webview的scrollview上添加的view可以响应touch吗?我添加后上边的按钮都不能点击了,例如上边的那个专注按钮,你的没问题吗?不知道是不是我哪里弄的有问题
      • a_只羊:博主总结了一套比较完善的 webView加 native 界面嵌套的处理方案,以后处理 webView 嵌套原生界面不妨可以试试这样的方法,应该是 webView 的动态高度的计算的升级版了,哈哈,也感谢博主对我提供的webView方法计算高度的反馈,让我完善相关的内容,相互探讨,加油加油哟~

      本文标题:wkWebView有headerView和footerView并

      本文链接:https://www.haomeiwen.com/subject/usegextx.html