【问题标题】:Dynamic UITableView row height using UIStackView?使用 UIStackView 的动态 UITableView 行高?
【发布时间】:2016-07-14 07:33:04
【问题描述】:

很惊讶这不是开箱即用的,因为这似乎是堆栈视图的一个重要用例。我有一个UITableViewCell 子类,它将 UIStackView 添加到 contentView。我在tableView(_cellForRowAtIndexPath:) 中向堆栈视图添加标签,并且 tableview 设置为使用动态行高,但它似乎不起作用,至少在 Xcode 7.3 中。我也觉得在堆栈视图中隐藏排列的子视图是可动画的,但这似乎也被打破了。

关于如何使其正常工作的任何想法?

class StackCell : UITableViewCell {
    enum VisualFormat: String {
        case HorizontalStackViewFormat = "H:|[stackView]|"
        case VerticalStackViewFormat = "V:|[stackView(>=44)]|"
    }

    var hasSetupConstraints = false
    lazy var stackView : UIStackView! = {
        let stack = UIStackView()
        stack.axis = .Vertical
        stack.distribution = .FillProportionally
        stack.alignment = .Fill
        stack.spacing = 3.0
        stack.translatesAutoresizingMaskIntoConstraints = false
        return stack
    }()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        contentView.addSubview(stackView)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func updateConstraints() {
        if !hasSetupConstraints {
            hasSetupConstraints = true
            let viewsDictionary: [String:AnyObject] = ["stackView" : stackView]
            var newConstraints = [NSLayoutConstraint]()
            newConstraints += self.newConstraints(VisualFormat.HorizontalStackViewFormat.rawValue, viewsDictionary: viewsDictionary)
            newConstraints += self.newConstraints(VisualFormat.VerticalStackViewFormat.rawValue, viewsDictionary: viewsDictionary)
            addConstraints(newConstraints)
        }
        super.updateConstraints()
    }

    private func newConstraints(visualFormat: String, viewsDictionary: [String:AnyObject]) -> [NSLayoutConstraint] {
        return NSLayoutConstraint.constraintsWithVisualFormat(visualFormat, options: [], metrics: nil, views: viewsDictionary)
    }

class ViewController: UITableViewController {

    private let reuseIdentifier = "StackCell"
    private let cellClass = StackCell.self

    override func viewDidLoad() {
        super.viewDidLoad()
        configureTableView(self.tableView)
    }

    private func configureTableView(tableView: UITableView) {
        tableView.registerClass(cellClass, forCellReuseIdentifier: reuseIdentifier)
        tableView.separatorStyle = .SingleLine
        tableView.estimatedRowHeight = 88
        tableView.rowHeight = UITableViewAutomaticDimension
    }

    private func newLabel(title: String) -> UILabel {
        let label = UILabel()
        label.text = title
        return label
    }

    // MARK: - UITableView
    override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 4
    }

    override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 44.0
    }

    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 10
    }

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier(reuseIdentifier, forIndexPath: indexPath) as! StackCell
        cell.stackView.arrangedSubviews.forEach({$0.removeFromSuperview()})
        cell.stackView.addArrangedSubview(newLabel("\(indexPath.section)-\(indexPath.row)"))
        cell.stackView.addArrangedSubview(newLabel("Second Label"))
        cell.stackView.addArrangedSubview(newLabel("Third Label"))
        cell.stackView.addArrangedSubview(newLabel("Fourth Label"))
        cell.stackView.addArrangedSubview(newLabel("Fifth Label"))
        return cell
    }

    override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
        let cell = tableView.cellForRowAtIndexPath(indexPath) as! StackCell
        for (idx, view) in cell.stackView.arrangedSubviews.enumerate() {
            if idx == 0 {
                continue
            }
            view.hidden = !view.hidden
        }
        UIView.animateWithDuration(0.3, animations: {
            cell.contentView.layoutIfNeeded()
            tableView.beginUpdates()
            tableView.endUpdates()

        })
    }
}

【问题讨论】:

    标签: ios xcode uitableview autolayout uistackview


    【解决方案1】:

    似乎要使其工作,需要在 UITableViewCell 的 init 中添加约束并添加到 contentView 而不是单元格的视图中。

    工作代码如下所示:

    import UIKit
    class StackCell : UITableViewCell {
        enum VisualFormat: String {
            case HorizontalStackViewFormat = "H:|[stackView]|"
            case VerticalStackViewFormat = "V:|[stackView(>=44)]|"
        }
    
        var hasSetupConstraints = false
        lazy var stackView : UIStackView! = {
            let stack = UIStackView()
            stack.axis = UILayoutConstraintAxis.Vertical
            stack.distribution = .FillProportionally
            stack.alignment = .Fill
            stack.spacing = 3.0
            stack.translatesAutoresizingMaskIntoConstraints = false
            stack.setContentCompressionResistancePriority(UILayoutPriorityRequired, forAxis: .Vertical)
            return stack
        }()
    
        override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
            super.init(style: style, reuseIdentifier: reuseIdentifier)
            contentView.addSubview(stackView)
            addStackConstraints()
        }
    
        required init?(coder aDecoder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
        }
    
        private func addStackConstraints() {
            let viewsDictionary: [String:AnyObject] = ["stackView" : stackView]
            var newConstraints = [NSLayoutConstraint]()
            newConstraints += self.newConstraints(VisualFormat.HorizontalStackViewFormat.rawValue, viewsDictionary: viewsDictionary)
            newConstraints += self.newConstraints(VisualFormat.VerticalStackViewFormat.rawValue, viewsDictionary: viewsDictionary)
            contentView.addConstraints(newConstraints)
            super.updateConstraints()
        }
    
        private func newConstraints(visualFormat: String, viewsDictionary: [String:AnyObject]) -> [NSLayoutConstraint] {
            return NSLayoutConstraint.constraintsWithVisualFormat(visualFormat, options: [], metrics: nil, views: viewsDictionary)
        }
    }
    

    【讨论】:

    • 每次我发布一个我以编程方式编写 UIStackViews 的问题时,每个人都讨厌我。所以我很高兴看到其他人这样做。也感谢您的回答;)
    • @Trip +1 以编程方式
    • 我还必须在 tableView 上设置estimatedRowHeight,然后它就神奇地开始工作了!
    猜你喜欢
    • 2017-01-19
    • 1970-01-01
    • 2021-06-13
    • 2018-06-07
    • 2019-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多