具有动态尺寸单元的可折叠Tableview

时间:2017-04-16 17:51:00

标签: ios swift uitableview dynamic nslayoutconstraint

我一直在尝试关注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)")
    }

正如您所看到的,问题是约束存在歧义,因此hasAmbigousLayouthasAmbigousLayout。折叠视图时没有错误。但是,当我展开视图时,也有高度约束,就会出现歧义。以下是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.minX{id: 776}, UIView:0x7fcfe856a790.minY{id: 771}, UIView:0x7fcfe856a790.Width{id: 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) 中的3个打印语句的输出:

KeyStroke

我试图将底部约束优先级降低为this问题中的sugested。我也尝试了很多其他网站,我遗憾地忘记了这些网站。 应用程序中的结果是视图甚至没有显示,因为它应该有一个红色背景,当我尝试打印子视图的帧时,宽度为0似乎很奇怪。

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

感谢您的时间 -Jorge

1 个答案:

答案 0 :(得分:0)

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

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

尝试重构您的代码......