2016-01-07 20 views
10

Meine Anwendung erstellt einen UITableViewController, der eine benutzerdefinierte tableHeaderView enthält, die eine beliebige Höhe haben kann. Ich habe mit einer Möglichkeit gekämpft, diesen Header dynamisch zu setzen, da es so aussieht, als hätten die vorgeschlagenen Wege diesen Header kurz geschnitten. Mein UITableViewController relevanten Code:Table_HeaderView-Höhe dynamisch festlegen

import UIKit 
import SafariServices 

class RedditPostViewController: UITableViewController, NetworkCommunication, SubViewLaunchLinkManager { 

    //MARK: UITableViewDataSource 
    var post: PostData? 
    var tree: CommentTree? 
    weak var session: Session! = Session.sharedInstance 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // Get post info from api 
     guard let postData = post else { return } 

     //Configure comment table 
     self.tableView.registerClass(RedditPostCommentTableViewCell.self, forCellReuseIdentifier: "CommentCell") 

     let tableHeader = PostView(withPost: postData, inViewController: self) 
     let size = tableHeader.systemLayoutSizeFittingSize(UILayoutFittingExpandedSize) 
     let height = size.height 
     let width = size.width 
     tableHeader.frame = CGRectMake(0, 0, width, height) 
     self.tableView.tableHeaderView = tableHeader 


     session.getRedditPost(postData) { (post) in 
      self.post = post?.post 
      self.tree = post?.comments 
      self.tableView.reloadData() 
     } 
    } 
} 

Dies ist in der folgenden falschen Layout-Ergebnisse: enter image description here Wenn ich die Zeile: tableHeader.frame = CGRectMake(0, 0, width, height) zu tableHeader.frame = CGRectMake(0, 0, width, 1000) die tableHeaderView wird sich richtig auslegen: enter image description here

Ich bin nicht sicher, was ich hier falsch mache. Auch benutzerdefinierte UIView Klasse, wenn dies hilft:

import UIKit 
import Foundation 

protocol SubViewLaunchLinkManager: class { 
    func launchLink(sender: UIButton) 
} 

class PostView: UIView { 

    var body: UILabel? 
    var post: PostData? 
    var domain: UILabel? 
    var author: UILabel? 
    var selfText: UILabel? 
    var numComments: UILabel? 

    required init?(coder aDecoder: NSCoder) { 
     fatalError("Not implemented yet") 
    } 

    init(withPost post: PostData, inViewController viewController: SubViewLaunchLinkManager) { 
     super.init(frame: CGRectZero) 

     self.post = post 
     self.backgroundColor = UIColor.lightGrayColor() 

     let launchLink = UIButton() 
     launchLink.setImage(UIImage(named: "circle-user-7"), forState: .Normal) 
     launchLink.addTarget(viewController, action: "launchLink:", forControlEvents: .TouchUpInside) 
     self.addSubview(launchLink) 

     selfText = UILabel() 
     selfText?.backgroundColor = UIColor.whiteColor() 
     selfText?.numberOfLines = 0 
     selfText?.lineBreakMode = .ByWordWrapping 
     selfText!.text = post.selfText 
     self.addSubview(selfText!) 
     selfText?.sizeToFit() 

     //let attributedString = NSAttributedString(string: "Test"/*post.selfTextHtml*/, attributes: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType]) 
     //selfText.attributedText = attributedString 

     body = UILabel() 
     body!.text = post.title 
     body!.numberOfLines = 0 
     body!.lineBreakMode = .ByWordWrapping 
     body!.textAlignment = .Justified 
     self.addSubview(body!) 

     domain = UILabel() 
     domain!.text = post.domain 
     self.addSubview(domain!) 

     author = UILabel() 
     author!.text = post.author 
     self.addSubview(author!) 

     numComments = UILabel() 
     numComments!.text = "\(post.numComments)" 
     self.addSubview(numComments!) 

     body!.translatesAutoresizingMaskIntoConstraints = false 
     domain!.translatesAutoresizingMaskIntoConstraints = false 
     author!.translatesAutoresizingMaskIntoConstraints = false 
     selfText!.translatesAutoresizingMaskIntoConstraints = false 
     launchLink.translatesAutoresizingMaskIntoConstraints = false 
     numComments!.translatesAutoresizingMaskIntoConstraints = false 

     let views: [String: UIView] = ["body": body!, "domain": domain!, "author": author!, "numComments": numComments!, "launchLink": launchLink, "selfText": selfText!] 
     //let selfTextSize = selfText?.sizeThatFits((selfText?.frame.size)!) 
     //print(selfTextSize) 
     //let metrics = ["selfTextHeight": selfTextSize!.height] 

        self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[body]-[selfText]-[domain]-|", options: [], metrics: nil, views: views)) 
     self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[body]-[selfText]-[author]-|", options: [], metrics: nil, views: views)) 
    self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[body]-[selfText]-[numComments]-|", options: [], metrics: nil, views: views)) 
    self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-[launchLink]-[numComments]-|", options: [], metrics: nil, views: views)) 
    self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[body][launchLink]|", options: [], metrics: nil, views: views)) 
    self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[selfText][launchLink]|", options: [], metrics: nil, views: views)) 
    self.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[domain][author][numComments][launchLink]|", options: [], metrics: nil, views: views)) 
} 

override func layoutSubviews() { 
    super.layoutSubviews() 
    body?.preferredMaxLayoutWidth = body!.bounds.width 
} 
} 

Antwort

35
//Dynamically determine the height of the tableHeaderView -> this code was the result of much effort. 
//http://collindonnell.com/2015/09/29/dynamically-sized-table-view-header-or-footer-using-auto-layout/ 
override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 

    if let headerView = tableView.tableHeaderView { 

     let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height 
     var headerFrame = headerView.frame 

     //Comparison necessary to avoid infinite loop 
     if height != headerFrame.size.height { 
      headerFrame.size.height = height 
      headerView.frame = headerFrame 
      tableView.tableHeaderView = headerView 
     } 
    } 
} 
+0

Awesome work lieber arbeiten !! –

+0

Capo, Gracias. Vielen Dank. –

+0

Ohne die letzte Zeile tableView.tableHeaderView = headerView funktioniert nicht. @TravMatth, könnten Sie mir erklären, warum wir tableView.tableHeaderView neu zuweisen müssen? – Giorgio

-1

Mehr gekürzte Version OP Antwort (mit dem Vorteil, dass das Layout passieren natürlich):

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 

    if let header = tableView.tableHeaderView { 
     let newSize = header.systemLayoutSizeFitting(UILayoutFittingCompressedSize) 
     header.frame.size.height = newSize.height 
    } 
} 

Da die Implementierung zeigt, Es gibt keine Entschuldigung dafür, dass Apple die Kopf-/Fußzeilen der Tabellenansicht nicht unterstützt, wie sie es jetzt mit Zellen tun. Frustrierend.

Danke an TravMatth für die ursprüngliche Antwort.

+0

Ich bin mir nicht sicher warum, aber dieses hat nicht für mich funktioniert, aber die OP Antwort hat. – Harris

+0

Dies ist, weil 'tableView.tableHeaderView.frame.size.height' schreibgeschützt ist. Sie müssen den Rahmen 'tableView.tableHeaderView.frame = ...' setzen. – mrcl

+0

Ich bin mir auch nicht sicher, warum das bei dir @Harris nicht funktioniert hat. CGSize height/width-Eigenschaften sind nicht mehr schreibgeschützt, daher sollte das nicht der Grund sein. Wenn jemand Einblick in ihr Problem mit dieser Lösung bietet, würde ich gerne helfen, zu diagnostizieren, wie ich immer noch dazu stehe. –

0

Wenn Sie immer noch Probleme mit dem Layout mit dem obigen Codebeispiel haben, besteht eine geringe Chance, dass Sie in der benutzerdefinierten Headeransicht translatesAutoresizingMaskIntoConstraints deaktiviert haben. In diesem Fall müssen Sie translatesAutoresizingMaskIntoConstraints wieder auf true setzen, nachdem Sie den Rahmen der Kopfzeile festgelegt haben.

Hier ist der Code-Beispiel verwende ich, und richtig auf iOS 11.

public override func viewDidLayoutSubviews() { 
    super.viewDidLayoutSubviews() 

    guard let headerView = tableView.tableHeaderView else { return } 

    let height = headerView.systemLayoutSizeFitting(UILayoutFittingCompressedSize).height 
    var headerFrame = headerView.frame 

    if height != headerFrame.size.height { 
     headerFrame.size.height = height 
     headerView.frame = headerFrame 
     tableView.tableHeaderView = headerView 

     if #available(iOS 9.0, *) { 
      tableView.layoutIfNeeded() 
     } 
    } 

    headerView.translatesAutoresizingMaskIntoConstraints = true 
} 
Verwandte Themen