web-dev-qa-db-ja.com

tableHeaderViewの高さを動的に設定する

私のアプリケーションは、任意の高さのカスタムtableHeaderViewを含むUITableViewControllerを作成します。提案された方法がこのヘッダーを短くカットしているように見えるので、このヘッダーを動的に設定する方法に苦労しています。私の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()
       }
    }
}
_

これにより、次の不正なレイアウトが発生します。

行を変更する場合:tableHeader.frame = CGRectMake(0, 0, width, height)からtableHeader.frame = CGRectMake(0, 0, width, 1000)にtableHeaderViewは正しくレイアウトされます:

ここで何を間違っているのかわかりません。また、カスタム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
}
}
_
20
TravMatth

この投稿 からコピーしました。 (詳細をお探しの場合は、必ずご覧ください)

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

OPの回答をより簡潔にしたバージョンで、レイアウトが自然に行われるという利点があります(このソリューションではビューを使用していることに注意してくださいWill LayoutSubviews):

override func viewWillLayoutSubviews() {
    super.viewWillLayoutSubviews()

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

これが示すように、Appleは、セルで現在行われているように自動テーブルビューヘッダー/フッターの高さをサポートしないという言い訳はありません。

元の回答をしてくれたTravMatthに感謝します。

10

を使用してヘッダーのフレームサイズを決定する

header.systemLayoutSizeFitting(UILayoutFittingCompressedSize)

上記の回答で示唆されているように、ヘッダービューが単一の複数行ラベルで構成されていた場合、私にとってはうまくいきませんでした。ラベルの改行モードを折り返すように設定すると、テキストが途切れます。

enter image description here

代わりに、Table Viewの幅と高さ0をターゲットサイズとして使用することでうまくいきました:

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

enter image description here

すべてをまとめる(拡張機能を使用したい):

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

そして次のように呼び出します:

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

これら2つのUITableViewデリゲートメソッドを実装するだけでうまくいきました:

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

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

上記のコードサンプルのレイアウトにまだ問題がある場合は、カスタムヘッダービューでtranslatesAutoresizingMaskIntoConstraintsを無効にする可能性がわずかにあります。その場合、ヘッダーのフレームを設定した後、translatesAutoresizingMaskIntoConstraintstrueに戻す必要があります。

以下は、私が使用し、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
}
0
emrekyv