WebViewを含むセルを含むテーブルビューがあります。セルの高さをwebViewの高さと一致させます。
これは私が使用するコードです:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("newsCell") as! NewsTableViewCell
cell.webView.loadHTMLString("test<br>test<br>test<br>test<br>test<br>test", baseURL: nil)
cell.webView.delegate = self
var webFrame = cell.webView.frame
var cellFrame = cell.frame
cell.frame = CGRectMake(cellFrame.Origin.x, cellFrame.Origin.y, cellFrame.width, webFrame.height + 20)
cell.backgroundColor = UIColor.redColor()
return cell
}
func webViewDidFinishLoad(webView: UIWebView) {
println("finished loading")
var frame = webView.frame
frame.size.height = 1
webView.frame = frame
var fittingSize = webView.sizeThatFits(CGSizeZero)
frame.size = fittingSize
webView.frame = frame
var height: CGFloat = frame.height
println(height)
webView.frame = CGRectMake(frame.Origin.x, frame.Origin.x, frame.size.width, frame.size.height)
newsTable.beginUpdates()
newsTable.endUpdates()
}
そして、これが結果です: https://postimg.cc/image/8qew1lqjj/
WebViewは正しい高さですが、セルはそうではありません。この問題を修正するにはどうすればよいですか?
TableViewはセル自体のサイズを変更します。tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
デリゲートメソッドを実装するだけです。
はい、最初はWebViewの高さはわかりませんが、計算してからTableViewにセルをリロードするように依頼できます。このようなもの:
class TableViewController: UITableViewController, UIWebViewDelegate
{
var content : [String] = ["test1<br>test1<br>test1<br>test1<br>test1<br>test1", "test22<br>test22<br>test22<br>test22<br>test22<br>test22"]
var contentHeights : [CGFloat] = [0.0, 0.0]
// ...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("newsCell", forIndexPath: indexPath) as! NewsTableViewCell
let htmlString = content[indexPath.row]
let htmlHeight = contentHeights[indexPath.row]
cell.webView.tag = indexPath.row
cell.webView.delegate = self
cell.webView.loadHTMLString(htmlString, baseURL: nil)
cell.webView.frame = CGRectMake(0, 0, cell.frame.size.width, htmlHeight)
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return contentHeights[indexPath.row]
}
func webViewDidFinishLoad(webView: UIWebView)
{
if (contentHeights[webView.tag] != 0.0)
{
// we already know height, no need to reload cell
return
}
contentHeights[webView.tag] = webView.scrollView.contentSize.height
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: webView.tag, inSection: 0)], withRowAnimation: .Automatic)
}
// ...
}
私にとっては、動的でWebViewにHtml Stringをロードする簡単な方法です。
最初にスクロールを無効にしてTableViewCellのtextViewを取得し、次にWebViewを取得し、ContentViewを使用して4面すべてにゼロ制約を適用します。次のコードに示すように、textviewとWebView.Nowの両方に同じ高さの制約を与え、両方のビューに同じテキストを与えます。
Clean UIの場合XIBまたはstoryBoardからtextViewを非表示にします。
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tableviewcell") as! tableviewcell
let theString : String = "</p><img src='https://pbs.twimg.com/profile_images/655066410087940096/QSUlrrlm.png' width=100 height=100 /><h2>Subheader</h2>"
let theAttributedString = try! NSAttributedString(data: theString.data(using: String.Encoding.utf8, allowLossyConversion: false)!,options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil)
cell.textview.attributedText = theAttributedString
cell.webview.loadHTMLString(theString, baseURL: nil)
return cell
}
Swift 4
ifau'sSwift 4、UITableView
の代わりにUITableViewController
を使用して、回答を修正しました。
ストーリーボードで、UITableView
を取得します。プロトタイプセルを1つ追加します。セルのreloadIdentifierを「cell
」のままにします。 webView
をセルにドラッグし、先頭、末尾、上部および下部の制約を0に設定します。セルクラスをTableViewCell
に設定します
TableViewCell.Swift
WebViewアウトレットをストーリーボードに接続します。
import UIKit
class TableViewCell: UITableViewCell {
@IBOutlet weak var webView: UIWebView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
ViewController.Swift
TableViewアウトレットをストーリーボードに接続します。
import UIKit
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIWebViewDelegate {
@IBOutlet weak var tableView: UITableView!
var content : [String] = ["test1<br>test1<br>test1", "test22<br>test22<br>test22<br>test22<br>test22<br>test22"]
var contentHeights : [CGFloat] = [0.0, 0.0]
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
tableView.dataSource = self
tableView.delegate = self
}
public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{
return content.count
}
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell : TableViewCell = tableView.dequeueReusableCell(withIdentifier: "cell") as! TableViewCell
let htmlString = content[indexPath.row]
let htmlHeight = contentHeights[indexPath.row]
cell.webView.tag = indexPath.row
cell.webView.delegate = self
cell.webView.loadHTMLString(htmlString, baseURL: nil)
cell.webView.frame = CGRect(x: 0, y: 0, width: cell.frame.size.width, height: htmlHeight)
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if contentHeights[indexPath.row] != 0 {
return contentHeights[indexPath.row]
}
}
public func webViewDidFinishLoad(_ webView: UIWebView){
if (contentHeights[webView.tag] != 0.0)
{
// we already know height, no need to reload cell
return
}
contentHeights[webView.tag] = webView.scrollView.contentSize.height
tableView.reloadRows(at: [IndexPath(row: webView.tag, section: 0)], with: .automatic)
}
}
WebViewの高さを計算した後tableViewcell height DispatchQueue.main.async
を再ロードするためにDispatchQueueを使用します。
func webViewDidFinishLoad(_ webView: UIWebView)
{
var frame : CGRect = webVwModule.frame;
frame.size.height = 1;
self.webVwModule.frame.size = webVwModule.sizeThatFits(.zero)
frame.size = self.webVwModule.frame.size;
webView.frame = frame;
webViewContentHeight = self.webVwModule.frame.size.height;
isWebViewLoaded = true
DispatchQueue.main.async(execute: { () -> Void in
self.tableView.beginUpdates()
self.tableView.endUpdates()
})
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return webViewContentHeight!
}
var heightOfWebview=0
func webViewDidFinishLoad(_ aWebView: UIWebView)
{
var frame: CGRect = aWebView.frame
frame.size.height = 1
aWebView.frame = frame
let fittingSize = aWebView.sizeThatFits(CGSize.zero)
frame.size = fittingSize
aWebView.frame = frame
heightOfWebview = Int(fittingSize.height)
tableView.beginUpdates()
tableView.endUpdates()
print("Calling webViewDidFinishLoad. Cell size value: \(heightOfWebview)")
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return CGFloat(220+heightOfWebview) /// 220 is my static value
}
最良の方法は私のために働いた。
var heightOfWebview: CGFloat = 0
func webViewDidFinishLoad(_ aWebView: UIWebView)
{
var frame: CGRect = aWebView.frame
frame.size.height = 1
aWebView.frame = frame
let fittingSize = aWebView.sizeThatFits(CGSize.zero)
frame.size = fittingSize
aWebView.frame = frame
heightOfWebview = Int(fittingSize.height)
tableView.beginUpdates()
tableView.endUpdates()
print("Calling webViewDidFinishLoad. Cell size value: \(heightOfWebview)")
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return heightOfWebview
}
最も簡単でエレガントな方法は
読み込みが完了したwebviewデリゲートを追加し、contentSizeの高さを定数の高さレイアウト制約に設定します。
テーブルビューのインスタンスを保持するか、メインテーブルビューへのデリゲート-ブロック-クロージャーを作成します。
class WebViewTableViewCell: UITableViewCell {
weak var viewController: ViewController? = nil
@IBOutlet weak var webView: UIWebView!
@IBOutlet weak var heightLayoutConstraint: NSLayoutConstraint!
override func awakeFromNib() {
super.awakeFromNib()
webView.loadRequest(URLRequest(url: URL(string: "https://tinhte.vn")!))
webView.delegate = self
webView.scrollView.isScrollEnabled = false
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension WebViewTableViewCell: UIWebViewDelegate {
func webViewDidFinishLoad(_ webView: UIWebView) {
heightLayoutConstraint.constant = webView.scrollView.contentSize.height
viewController?.tableView.beginUpdates()
viewController?.tableView.endUpdates()
}
}
もう1つ考慮すべき解決策があります。高さの制約を作成し、UITableViewCell
クラスにリンクします。次に、デリゲートメソッドfunc webViewDidFinishLoad(_ webView: UIWebView)
を実装し、呼び出されたら、高さの制約をwebView.scrollView.contentSize.height
に等しくなるように設定します。
class WebViewTableViewCell: UITableViewCell {
weak var viewController: ViewController? = nil
@IBOutlet weak var webView: UIWebView!
@IBOutlet weak var heightLayoutConstraint: NSLayoutConstraint!
override func awakeFromNib() {
super.awakeFromNib()
webView.loadRequest(URLRequest(url: URL(string: "https://tinhte.vn")!))
webView.delegate = self
webView.scrollView.isScrollEnabled = false
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
extension WebViewTableViewCell: UIWebViewDelegate {
func webViewDidFinishLoad(_ webView: UIWebView) {
heightLayoutConstraint.constant = webView.scrollView.contentSize.height
viewController?.tableView.beginUpdates()
viewController?.tableView.endUpdates()
}
}