UILabels 两列多行的复杂动态集合 iOS

Complex Dynamic Collection Of UILabels Two Columns and Multiple Rows iOS

我一直在思考如何在我的 tableViewCell 中设置这种布局。见照片:

更多信息:

  1. 数据是动态的。可能还有其他日子,每一天可能由多组时间组成。
  2. 我的单元格 dynamic/responsive 高度当然需要自动布局。

我已经做了:

  1. 我确实尝试过使用 IB 来做到这一点。
  2. 我也以编程方式尝试过。
  3. 无论是在 IB 中还是以编程方式,我都使用了 UIStackView。但是有点难设置。
  4. 我正在考虑使用 UIViews 作为容器来设置它,就像 UIStackView 但不那么复杂。

我正在逐行进行设置。首先是垂直排列时间,然后将其视图或堆栈视图与日期水平配对。之后其他日子也一样。

为了问题的正式性,这是我单元格中用于设置此布局的部分代码,我建议不要费力阅读它,我相信我知道我在做什么,而且我想我只需要你们的另一种方法。

var job: Job! {
    didSet {

        _ = self.subviews.map {
            if [=11=] is UIStackView {
                [=11=].removeFromSuperview()
            }
        }

        GPLog(classSender: self, log: "Setting up stackview for JobShift")

        // Add the main vertical stackView

        let stackView_Vertical = UIStackView(frame: .zero)
        stackView_Vertical.translatesAutoresizingMaskIntoConstraints = false
        stackView_Vertical.alignment = .fill
        stackView_Vertical.distribution = .fillProportionally
        stackView_Vertical.axis = .vertical
        stackView_Vertical.spacing = 16.0
        self.addSubview(stackView_Vertical)

        // Add constraints

        stackView_Vertical.topAnchor.constraint(equalTo: self.topAnchor, constant: 15.0).isActive = true
        stackView_Vertical.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -15.0).isActive = true
        stackView_Vertical.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 15.0).isActive = true
        stackView_Vertical.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -15.0).isActive = true

        if let dummyJson = self.readJson() {
            if let shiftsJsonArray = dummyJson.array {
                for shiftJson in shiftsJsonArray {

                    let newShift = DummyDataShift(json: shiftJson)

                    if let day = newShift.day,
                        let schedules = newShift.schedule {
                        let generatedStackView = self.generateDayScheduleStackView(day: day, schedules: schedules)
                        stackView_Vertical.addArrangedSubview(generatedStackView)
                    }
                }
            }
        }
    }
}

// MARK: - Functions

// Generate the full schedule stack view.
func generateDayScheduleStackView(day: String, schedules: [DummyDataSchedule]) -> UIStackView {

    // label day (e.g. MONDAY)
    let newLabel_Day = self.shiftLabel
    newLabel_Day.translatesAutoresizingMaskIntoConstraints = false
    newLabel_Day.text = day
    newLabel_Day.backgroundColor = .red
    newLabel_Day.heightAnchor.constraint(equalToConstant: 30.0).isActive = true

    // Prepare the vertical schedule stackView
    let stackView_Schedule = UIStackView(frame: .zero)
    stackView_Schedule.alignment = .fill
    stackView_Schedule.distribution = .fillEqually
    stackView_Schedule.axis = .vertical

    // Add the schedules to the stackView vertically
    for schedule in schedules {
        let newLabel_Time = self.shiftLabel
        newLabel_Time.text = "\(schedule.timeIn!) - \(schedule.timeOut!)"
        newLabel_Time.backgroundColor = self.getRandomColor()
        newLabel_Time.translatesAutoresizingMaskIntoConstraints = false
        newLabel_Time.heightAnchor.constraint(equalToConstant: 30.0).isActive = true

        stackView_Schedule.addArrangedSubview(newLabel_Time)
    }

    // Prepare the horizontal dayScheduleStackView
    let stackView_DaySchedule = UIStackView(frame: .zero)
    stackView_DaySchedule.alignment = .fill
    stackView_DaySchedule.distribution = .fillProportionally
    stackView_DaySchedule.axis = .horizontal

    // Add arranged subViews
    stackView_DaySchedule.addArrangedSubview(newLabel_Day)
    stackView_DaySchedule.addArrangedSubview(stackView_DaySchedule)


    return stackView_DaySchedule
}

问题是:很多关于破坏约束的警告,我知道如何设置和修复约束。但是当我修复它时,没有任何显示。我觉得我在浪费时间推动并努力继续这种方法。所以我想如果我征求建议,我会很多吗?

有多种方法可以解决您的问题。我将尝试为您提供一种方法。

1) 使用 TableView,每个部分单元格包含 "day of the week" 标签加上垂直 StackView 的时间标签(使用等间距)。

2) 如果你正确地设置了约束,你可以 return UITableViewAutomaticDimension on sizeForRow: delegate.

override func tableView(_ tableView: UITableView, heightForRowAt 
    indexPath: IndexPath) -> CGFloat {
    return UITableViewAutomaticDimension
}

然后,在 cellForRowAt 方法中,您可以将标签附加到带有时间的垂直堆栈视图。每个单元格的高度将是正确的,因为它来自约束条件。

实际上,我认为堆栈视图是一种非常好的方式。它们是关于按行和列排列事物,这正是您想要做的。在 Interface Builder 中,仅使用堆栈视图,我可以毫不费力地安排一些标签来模仿您的规范:

堆栈视图令人愉快的一点是,一旦它们被正确配置,它们就会随着排列的子视图的添加或删除而适应。因此,它们完全按照您想要的方式动态变化。