2016-01-07 6 views
10

Мое приложение создает UITableViewController, который содержит пользовательский tableHeaderView, который может иметь произвольную высоту. Я изо всех сил пытался установить этот заголовок динамически, так как кажется, что предлагаемые способы сократили этот заголовок. Соответствующий код Мои UITableViewController в:Настройка таблицыHeaderView height динамически

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

Capo, 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 после того, как вы установите рамку заголовка.

Вот пример кода, я использую, и правильно работать на прошивке 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 
} 
Смежные вопросы