2015-09-13 20 views
15

Ich habe eine Tabellenansicht mit Zellen, die ein WebView in ihnen haben, ich möchte die Höhe der Zelle mit der Höhe des WebView übereinstimmen. UITableViewCell mit UIWebView Dynamische Höhe

der Code Dies ist ich benutze:

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() 
}  

Und das ist das Ergebnis: http://postimg.org/image/8qew1lqjj/

Die WebView ist die richtige Höhe, aber die Zelle nicht, wie kann ich dieses Problem beheben?

Antwort

19

TableView wird Zellen selbst skalieren, Sie müssen nur tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat Delegate-Methode implementieren.

Ja, Sie kennen die Höhe von WebView zunächst nicht, aber Sie können es berechnen und dann TableView bitten, Zelle neu zu laden. Etwas wie dieses:

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) 
    } 

    // ... 
} 
+0

Aus irgendeinem Grund die Tabelle wie folgt erscheint: http://postimg.org/image/wp43uf291, wissen Sie, warum? – OmerN

+0

@OmerN, meinst du schwarze Linien? Ich denke, es ist das gleiche Problem wie in [dieser Frage] (http://stackoverflow.com/q/21420137/683917). – ifau

+0

Das funktioniert, hat aber ein Problem. Der Aufruf loadHTMLString kann eine Web-Content-Anfrage enthalten, wenn der Traffic verdoppelt wird und die App bei langsamem Web-Aufruf langsam wird. – Ripley

-4

Implementieren Sie den UITab View-Delegaten heightforrowatindexpath, um die Höhe des Webview-Rahmens zurückzugeben.

+0

aber ich bekomme nur die webView Höhe nach der webViewDidFinishLoad Funktion – OmerN

2

Es ist Arbeit für mich, einfache Möglichkeit, HTML-String auf WebView mit dynamischen laden.

Zuerst nehmen Sie TextView in TableViewCell mit Scroll deaktivieren und dann WebView, Apply Null Einschränkung auf allen 4 Seite mit ContentView. Geben Sie nun sowohl textview als auch WebView dieselbe Höhenkondensität an. Geben Sie nun beiden Ansichten denselben Text wie unten gezeigt.

Für saubere Benutzeroberfläche Text ausblendenVon XIB oder storyBoard.

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 
} 
+0

Auch muss eine versteckte Textansicht haben, aber diese Methode funktioniert auch für mich. – bubuxu

+0

Danke, ja, Sie müssen TextView verstecken. Ich fügte hinzu, dass auf Antwort – Ujesh

+0

Ich denke, das wird nicht funktionieren, wenn Ihr HTML-Format enthält img oder Styling wie in Textview jedes Tag wird als Text wie betrachten: , So Höhe wird auch ändern. – Sibasish

0
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 
} 
+0

Es ändert nicht die Größe des WebView entsprechend seinem Inhalt. –

1

Nachdem die Höhe des webview Berechnung Verwendung DispatchQueue zur Höhen tableViewcell Nachladen DispatchQueue.main.async .Es vermeidet abnormal leere Räume und crash während webview Rahmen

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! 
} 
1

Swift 4 Nachladen

ifaus Antwort geändert für Swift 4 unter Verwendung von UITableView anstelle von UITableViewController.

Im Storyboard nehmen Sie eine UITableView. Fügen Sie 1 Prototyp-Zelle hinzu. Halten Sie den reuseIdentifier der Zelle auf "cell". Ziehen Sie ein webView in die Zelle und eingestellt führenden, nachlauf, obere und untere Beschränkungen auf 0 gesetzt die Zellklasse zu TableViewCell

TableViewCell.swift

Connect webView Auslass Storyboard:

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

den Auslass zum Storyboard Tableview Connect:

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) 
    } 
} 
+0

Hinzugefügt 'contentHeights [indexPath.row]! = 0' verhindert autoLayout-Unterbrechung – Jack

0

Der beste Weg für mich gearbeitet.

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 
} 
Verwandte Themen