具有动态调整单元格的可折叠表格视图

Posted

技术标签:

【中文标题】具有动态调整单元格的可折叠表格视图【英文标题】:Collapsable Tableview with Dynamic sizing cells 【发布时间】:2017-04-16 17:51:00 【问题描述】:

我一直在尝试遵循this github 教程,但是它们不是静态单元格,而是动态的,因为我不知道编译时的高度。 在 tableViewController 中,我将heightForRowAt 设置为0UITableViewAutomaticDimension,具体取决于该部分是否折叠。与estimatedHeightForRowAt类似,该值是0,如果展开,则为更高的值。

现在解决问题,我已将UITableViewCell 子类化,当调用 cellForRowAt 时,它将添加一个如下所示的子视图:

override func addSubview(_ view: UIView) 
        guard view != nil else return

        for view in self.subviews 
            view.removeFromSuperview()
        

        super.addSubview(view)
        //view.applyLeadingAndTrailingPinConstraint(toSuperview: 0)
        //view.applyTopAndBottomPinConstraint(toSuperview: 0)

        let addedView = self.subviews[0]

        let bottom = NSLayoutConstraint(item: addedView, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 0)
        bottom.priority = 750
        bottom.isActive = true
        NSLayoutConstraint(item: addedView, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: addedView, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: addedView, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: addedView, attribute: .centerX, relatedBy: .equal, toItem: self, attribute: .centerX, multiplier: 1, constant: 0).isActive = true
        NSLayoutConstraint(item: addedView, attribute: .centerY, relatedBy: .equal, toItem: self, attribute: .centerY, multiplier: 1, constant: 0).isActive = true

        //NSLayoutConstraint.reportAmbiguity(v: self)
        if addedView.hasAmbiguousLayout 
            print("Horizontal: \(addedView.constraintsAffectingLayout(for: .horizontal))")
            print("Vertical: \(addedView.constraintsAffectingLayout(for: .vertical))")
            print("Trace: \(addedView.value(forKey: "_autolayoutTrace"))")
        
        //addedView.exerciseAmbiguityInLayout()

        //print("self: \(self.frame), subview: \(self.subviews[0].frame)")
    

如您所见,问题在于约束有歧义,因此使用了hasAmbigousLayout。当视图折叠时没有错误。然而,当我展开视图时,也有高度限制,就会出现歧义。以下是hasAmbigousLayout内的3条打印语句的输出:

Horizontal: []
Vertical: [<NSLayoutConstraint:0x60800028ea10 UIView:0x7fcfe856a790.height == 100   (active)>]
Trace: Optional(
•ViraVira_Info.WellnessCell:0x7fcfe8859a00'cell', MISSING HOST CONSTRAINTS
|   *UIView:0x7fcfe856a790- AMBIGUOUS LAYOUT for UIView:0x7fcfe856a790.minXid: 776, UIView:0x7fcfe856a790.minYid: 771, UIView:0x7fcfe856a790.Widthid: 778

Legend:
    * - is laid out with auto layout
    + - is laid out manually, but is represented in the layout engine because translatesAutoresizingMaskIntoConstraints = YES
    • - layout engine host)

我已尝试按照this 问题中的建议降低底部约束优先级。我还尝试了许多其他网站,但遗憾的是我忘记了这些网站。 应用程序中的结果是视图甚至没有显示,因为它应该有一个红色背景,当我尝试打印子视图的框架时,宽度为 0,这看起来很奇怪。

我可能在约束方面犯了一个愚蠢的错误,但经过 2 天的尝试,我仍然无法弄清楚。

感谢您的宝贵时间 -豪尔赫

【问题讨论】:

【参考方案1】:

有几个问题需要注意(并且可能是问题的一部分):

override func addSubview(_ view: UIView) -> 我认为这不是您的代码的正确位置。我已经开发了几年 ios 并且从来没有理由重写该方法。视图布局应该在 Interface Builder 或父视图中完成。 guard view != nil else return -> 应该给你一个警告,因为 view 不是可选的(UIView?),所以它不能为零。这项检查根本没有用处。 for view in self.subviews view.removeFromSuperview() super.addSubview(view) -> 这将删除之前添加的所有视图,最后添加的视图将赢得比赛,这完全出乎 addSubview 的调用者的意料 - 如果一个单元格添加多个子视图,这将导致麻烦和头痛。 let addedView = self.subviews[0] -> 必须是相等视图,那为什么不在后面的代码中使用视图呢? 6 * NSLayoutConstraint -> 视图通常由 4 个约束定位,2 个垂直和 2 个水平 - 我认为你应该删除最后两个(中心约束) - 这可能是你的问题。

尝试重构您的代码...

【讨论】:

感谢您的回答,但让我们分分合合吧。 1)也许没有必要继承addSubview,但这是最简单的,但我会将约束移动到layoutSubviews。 2) 这实际上是一个错误,因为我作为参数传递的值是一个 UIView!,并给了我一个 nil 值,这不应该是可能的,但它确实发生了。 3)我不知道如何创建cellForRowAt所以我通过添加一个子视图来解决它,这会导致多次相同的视图,所以我先删除另一个然后重新添加它,也许你可以帮我找到一个更好的解决方案。 4) 那只是一个错误:)。 5)我试图只用 4 来做,但它没有改变任何东西。我仍然遇到同样的错误。 2) 您不应该使用变通方法来修复错误。尝试找到 nil 情况的原因并修复它。 3)已经有一些关于表格视图和单元格加载的文档。太多的评论或答案。见:***.com/documentation/ios/791/…

以上是关于具有动态调整单元格的可折叠表格视图的主要内容,如果未能解决你的问题,请参考以下文章

调整单元格大小时如何使表格视图动画平滑

使用自动布局约束动态调整表格视图单元格的大小

以编程方式动态调整多行 UILabel 和随附的表格视图单元格

具有调整单元格动画大小的动态单元格大小

具有动态高度单元格但所有单元格同时显示的 iOS 表格视图

Swift 3 - 已展开第一个单元格的可展开表格视图单元格