在我的iOS应用中,我要显示包含HTML的多个项目。为此,我构建了一个 NewsListViewController ,其中包含一个 UITableView 。对于该 UITableView (导出:newsListTableView),我创建了一个名为 NewsTableViewCell 的自定义 UITableViewCell ,它将通过委托(delegate)加载到该表中。 NewsTableViewCell 拥有一个 WKWebKit 控件,该控件将显示我的HTML。这是我的代码:

NewsListViewController.swift

import UIKit

class NewsListViewController: UIViewController {

    @IBOutlet weak var newsListTableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.newsListTableView.delegate = self
        self.newsListTableView.dataSource = self
        self.newsListTableView.register(UINib(nibName: "NewsTableViewCell", bundle: nil), forCellReuseIdentifier: "cell")
    }

}

extension NewsListViewController: UITableViewDelegate {

}

extension NewsListViewController: UITableViewDataSource {

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
    {
        return 300.0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! NewsTableViewCell
        cell.titleText = "My Title"
        cell.dateTimeText = "01.01.1998"
        cell.contentHtml = "<html><head><meta name=\"viewport\" content=\"initial-scale=1.0\" /><style>html, body { margin: 0; padding: 0; font-size: 15px; }</style></head><body><b>Hello News</b><br />Hello News<br />Hello News<br />Hello News</body></html>"
        return cell
    }

}

NewsTableViewCell.xib

ios - 如何使用基础WKWebKit自动调整UITableViewCell的大小,使其尊重Web View 的内容?-LMLPHP

我的 WKWebKit (导出:newsContentPreviewWebView)位于 UIView (导出:newsContentViewContainer)内部,具有适当的约束条件,可以随 UIView 一起增长。我的 UIView 也带有适当的约束,可以随整个单元一起增长。

NewsTableViewCell.swift
import UIKit
import WebKit

@IBDesignable class NewsTableViewCell: UITableViewCell {

    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var dateTimeLabel: UILabel!
    @IBOutlet weak var newsContentViewContainer: UIView!
    @IBOutlet weak var newsContentPreviewWebView: WKWebView!

    @IBInspectable var titleText: String? {
        get {
            return self.titleLabel.text
        }
        set(value) {
            self.titleLabel.text = value
        }
    }

    @IBInspectable var dateTimeText: String? {
        get {
            return self.dateTimeLabel.text
        }
        set(value) {
            self.dateTimeLabel.text = value
        }
    }

    @IBInspectable var contentHtml: String? {
        get {
            return nil
        }
        set(value) {
            self.newsContentPreviewWebView.loadHTMLString(value ?? "", baseURL: nil)
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()

        self.newsContentPreviewWebView.navigationDelegate = self
    }

}

extension NewsTableViewCell: WKNavigationDelegate {
}

结果如下:

ios - 如何使用基础WKWebKit自动调整UITableViewCell的大小,使其尊重Web View 的内容?-LMLPHP

现在,我希望单元格尽可能小,但仍要显示完整的 WKWebKit 内容。

当我删除...
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
    return 300.0
}

...从 NewsListViewController.swift 中开始,单元格高度将仅遵循 WKWebKit 控件上方的标签:

ios - 如何使用基础WKWebKit自动调整UITableViewCell的大小,使其尊重Web View 的内容?-LMLPHP

我认为这正在发生,因为当应用程序调整单元格大小时,我的 WKWebKit 的内容未加载。

我试着通过解决 WKWebKit 的>>来完成此问题,以解决此问题,在我的 NewsTableViewCell.swift 中完成导航<
extension NewsTableViewCell: WKNavigationDelegate {
    func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        webView.evaluateJavaScript("document.readyState", completionHandler: { (complete, error) in
            if complete != nil {
                webView.evaluateJavaScript("document.body.scrollHeight", completionHandler: { (height, error) in
                    let h: CGFloat = height as! CGFloat

                    let newsContentFrame: CGRect = self.newsContentViewContainer.frame
                    self.newsContentViewContainer.frame = CGRect(x: newsContentFrame.minX, y: newsContentFrame.minY, width: newsContentFrame.width, height: h)

                    let tableCellFrame: CGRect = self.frame
                    self.frame = CGRect(x: tableCellFrame.minX, y: tableCellFrame.minY, width: tableCellFrame.width, height: tableCellFrame.height + h)
                })
            }
        })
    }
}

结果如下:

ios - 如何使用基础WKWebKit自动调整UITableViewCell的大小,使其尊重Web View 的内容?-LMLPHP

单元格重叠,这表示我正在尝试以错误的方式解决此问题。

自动调整自定义表单元格的大小以适合其所有内容(包括 WKWebKit 的内容)的正确方法是什么?

最佳答案

问题是您永远不会给自己的细胞一个高度。手动设置框架



不好。您应该始终使用专用的委托(delegate)方法或估计的行高技术(Using Auto Layout in UITableView for dynamic cell layouts & variable row heights)。

问题很棘手:您需要等待webview加载以计算其高度。但是调用heightForCell时需要它的高度,以便在加载Webview的内容之前。

我看到5个解决方案:

  • 您将表 View 转换为包含所有新闻的巨型Web View 。然后您手动将元数据注入(inject)html
  • 您解析html并提取所需的信息。仅当所有新闻html具有相同的结构时,才有可能这样做。这也很难(RegEx match open tags except XHTML self-contained tags)。
  • 您照原样进行。但是,当调用completionHandler时,您将调用一个委托(delegate)(例如,您的viewcontroller),该委托(delegate)将重新加载相应的单元格,并为其提供刚刚计算出的正确高度。这个解决方案很简单,但是在每次加载之前,您都需要在单元格上设置错误的高度。因此,您可以在单元格中定义加载状态,但是当单元格即将出现时,您总是会有一点小故障。
  • 您将加载所有单元格的内容,并在显示表格 View 之前在后台线程上计算它们的相应高度。您可以为每个单元格使用Operation,它将等待单元格的html加载并评估给定的javascript。完成所有操作后,重新加载表格 View
  • 更改您的设计:选择一个单元格时,仅显示新闻列表并在单独的 View Controller 中加载新闻内容
  • 关于ios - 如何使用基础WKWebKit自动调整UITableViewCell的大小,使其尊重Web View 的内容?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/48463531/

    10-10 19:58