priority español code ios swift autolayout

ios - español - Configurando tableHeaderView height dinámicamente



constraints xcode 10 (5)

Mi aplicación crea un UITableViewController que contiene un tableHeaderView personalizado que puede tener una altura arbitraria. He estado luchando con una manera de establecer este encabezado dinámicamente, ya que parece que las formas sugeridas han sido cortar este encabezado. El código relevante de mi UITableViewController:

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

Esto resulta en el siguiente diseño incorrecto:

Si cambio la línea: tableHeader.frame = CGRectMake(0, 0, width, height) a tableHeader.frame = CGRectMake(0, 0, width, 1000) el tableHeaderView se desplegará correctamente:

No estoy seguro de lo que estoy haciendo incorrectamente aquí. Además, la clase UIView personalizada, si esto ayuda:

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


Copiado de este post . (Asegúrate de verlo si buscas más detalles)

override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() if let headerView = tableView.tableHeaderView { let height = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).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 } } }


Determinando el tamaño del marco del encabezado usando

header.systemLayoutSizeFitting(UILayoutFittingCompressedSize)

Como sugerí en las respuestas anteriores, no funcionó para mí cuando mi vista de encabezado consistía en una sola etiqueta multilínea. Con el modo de salto de línea de la etiqueta configurado para ajustarse, el texto simplemente se corta:

En su lugar, lo que funcionó para mí fue usar el ancho de la vista de tabla y una altura de 0 como tamaño de destino:

header.systemLayoutSizeFitting(CGSize(width: tableView.bounds.width, height: 0))

Poniéndolo todo junto (prefiero usar una extensión):

extension UITableView { func updateHeaderViewHeight() { if let header = self.tableHeaderView { let newSize = header.systemLayoutSizeFitting(CGSize(width: self.bounds.width, height: 0)) header.frame.size.height = newSize.height } } }

Y llámalo así:

override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() tableView.updateHeaderViewHeight() }


La implementación de estos dos métodos de delegado de UITableView funcionó para mí:

-(CGFloat)tableView:(UITableView *)tableView estimatedHeightForHeaderInSection:(NSInteger)section { return 100; } -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return UITableViewAutomaticDimension; }


Si aún tiene problemas con el diseño con el ejemplo de código anterior, existe una pequeña posibilidad de que deshabilite translatesAutoresizingMaskIntoConstraints en la vista de encabezado personalizada. En ese caso, debe volver a establecer translatesAutoresizingMaskIntoConstraints en true después de configurar el marco del encabezado.

Aquí está el ejemplo de código que estoy usando y que funciona correctamente en 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 }


Versión más condensada de la respuesta de OP, con la ventaja de permitir que el diseño se realice de forma natural (tenga en cuenta que esta solución utiliza la vista de LayoutSubviews):

override func viewWillLayoutSubviews() { super.viewWillLayoutSubviews() if let header = tableView.tableHeaderView { let newSize = header.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize) header.frame.size.height = newSize.height } }

Como se muestra, no hay excusa para que Apple no admita alturas de encabezado / pie de página de vista de tabla automáticas como lo hacen ahora con celdas. Frustrante.

Gracias a TravMatth por la respuesta original.