2016-01-07 83 views
10

我的应用程序创建一个UITableViewController,它包含一个可以有任意高度的自定义tableHeaderView。我一直在努力动态地设置这个头,因为似乎建议的方法已经缩短了这个头。 我的UITableViewController的相关代码:动态设置tableHeaderView高度

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

这将导致以下不正确的布局: enter image description here 如果我改变路线:tableHeader.frame = CGRectMake(0, 0, width, height)tableHeader.frame = CGRectMake(0, 0, width, 1000)的tableHeaderView将自己正确的布局: enter image description here

我不知道我在这里做错了什么。此外,自定义UIView类,如果这能帮助:

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

回答

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

真棒工作亲爱的正常工作的代码示例! –

+0

投诉警察课,gracias。谢谢。 –

+0

没有最后一行tableView.tableHeaderView = headerView不起作用。 @TravMatth,你能解释我为什么我们必须重新分配tableView.tableHeaderView? – Giorgio

-1

以上精简版OP的回答(用允许布局自然发生的利益):

override func viewWillLayoutSubviews() { 
    super.viewWillLayoutSubviews() 

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

作为实施表明, Apple没有理由不支持自动表格视图页眉/页脚高度,因为他们现在使用单元格。令人沮丧。

感谢TravMatth的原始答案。

+0

我不知道为什么,但这个不适合我,但OP答案。 – Harris

+0

因为'tableView.tableHeaderView.frame.size.height'是只读的。你必须设置框架'tableView.tableHeaderView.frame = ...'。 – mrcl

+0

我也不确定为什么这不适合你@哈里斯。 CGSize高度/宽度属性不再是只读的,所以不应该是原因。如果任何人提供这个解决方案的问题的洞察力,我会很乐意帮助诊断,因为我仍然支持它。 –

0

如果您仍然遇到上述代码示例的布局问题,您可能会在自定义标题视图上禁用translatesAutoresizingMaskIntoConstraints。在这种情况下,您需要在设置标题帧后将translatesAutoresizingMaskIntoConstraints设置回true

下面是我使用,并在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 
}