Ячейки не появляются сначала, но показывают, прокручиваю ли я вниз и возвращаюсь - PullRequest
0 голосов
/ 10 мая 2019

У меня есть динамически изменяющиеся ячейки таблицы, которые имеют две метки друг над другом.Верхняя метка всегда содержит текст, а нижняя - иногда нет.После загрузки табличного представления ячейки без текста для нижней метки полностью исчезают, и отображается только их заголовок.Если я прокручиваю вниз и возвращаюсь вверх, эти ранее отсутствующие ячейки отображаются правильно.

Я думаю, что это как-то связано с моими ограничениями, но когда я пытаюсь настроить ограничения, я только ухудшил положение.

Как сделать ограничения такими, чтобы ячейки всегда появлялись сначала при загрузке экрана, в том числе когда на нижней метке нет текста?

Вот код для ячейки табличного представления:

class TransactionHistoryTableViewCell: UITableViewCell {

private var itemView = UIView()
private var itemNameLabel = UILabel()
private var sizeLabel = UILabel()

func setup(_ lineItem: MenuItem) {
    contentView.backgroundColor = .white
    configureItemNameLabel(lineItem)
    configureSizeLabel(lineItem)
    configureTransactionView(lineItem)
}

private func configureTransactionView(_ lineItem: MenuItem) {
    itemView.clipsToBounds = true
    itemView.layer.cornerRadius = 5
    itemView.layer.borderColor = UIColor.lightGray.cgColor
    itemView.layer.borderWidth = 0.5
    itemView.backgroundColor = .white
    contentView.addSubview(itemView)
    itemView.translatesAutoresizingMaskIntoConstraints = false
    itemView.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
    itemView.widthAnchor.constraint(equalTo: contentView.widthAnchor, multiplier: 0.8).isActive = true
    itemView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 4).isActive = true
    itemView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -4).isActive = true
}

private func returnText(_ menuItem: MenuItem) -> String {
    var text = ""
    guard let modifiers = menuItem.modifiers else { print("modifiers are nil"); return "" }
    if modifiers.isEmpty && menuItem.quantity == 1 {
        text = ""
    } else if !modifiers.isEmpty && menuItem.quantity == 1 {
        text = generateModifierText(menuItem)
    } else if !modifiers.isEmpty && menuItem.quantity > 1 {
        let theText = generateModifierText(menuItem)
        text = "\(theText); Quantity: \(menuItem.quantity)"
    } else {
        text = "Quantity: \(menuItem.quantity)"
    }
    return text
}

private func configureItemNameLabel(_ lineItem: MenuItem) {
    itemNameLabel.text = lineItem.name
    let fontSize = getSize(large: 14, medium: 13.5, small: 12)
    itemNameLabel.font = UIFont(name: AppFont.secondary.name, size: fontSize)
    itemNameLabel.numberOfLines = 0
    itemView.addSubview(itemNameLabel)
    itemNameLabel.translatesAutoresizingMaskIntoConstraints = false
    itemNameLabel.leftAnchor.constraint(equalTo: itemView.leftAnchor, constant: 15).isActive = true
    let verticalOffset = getSize(large: 10, medium: 7, small: 5)
    itemNameLabel.topAnchor.constraint(equalTo: itemView.topAnchor, constant: verticalOffset).isActive = true
    itemNameLabel.widthAnchor.constraint(equalToConstant: 195).isActive = true
    itemView.addSubview(sizeLabel)
    itemNameLabel.bottomAnchor.constraint(equalTo: sizeLabel.topAnchor, constant: -3).isActive = true
}

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()
    return label.frame.height
}

override func prepareForReuse() {
    super.prepareForReuse()
    itemNameLabel.text = ""
    sizeLabel.text = ""
}

private func configureSizeLabel(_ menuItem: MenuItem) {
    guard let modifiers = menuItem.modifiers else { print("modifiers are nil"); return }
    if modifiers.isEmpty && menuItem.quantity == 1 {
        sizeLabel.text = ""
    } else if !modifiers.isEmpty && menuItem.quantity == 1 {
        sizeLabel.text = generateModifierText(menuItem)
    } else if !modifiers.isEmpty && menuItem.quantity > 1 {
        let text = generateModifierText(menuItem)
        if text != "" {
            sizeLabel.text = "\(text); Quantity: \(menuItem.quantity)"
        } else {
            sizeLabel.text = "Quantity: \(menuItem.quantity)"
        }
    } else {
        sizeLabel.text = "Quantity: \(menuItem.quantity)"
    }
    sizeLabel.backgroundColor = .white
    sizeLabel.textColor = .gray
    sizeLabel.numberOfLines = 0
    let fontSize = getSize(large: 11, medium: 10.5, small: 9.5)
    sizeLabel.font = UIFont(name: AppFont.secondary.name, size: fontSize)
    sizeLabel.translatesAutoresizingMaskIntoConstraints = false
    sizeLabel.topAnchor.constraint(equalTo: itemNameLabel.bottomAnchor, constant: 3).isActive = true
    sizeLabel.leftAnchor.constraint(equalTo: itemNameLabel.leftAnchor).isActive = true
    sizeLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
    sizeLabel.bottomAnchor.constraint(equalTo: itemView.bottomAnchor, constant: -3).isActive = true
}

private func generateModifierText(_ menuItem: MenuItem) -> String {
    var text = ""
    guard let modifiers = menuItem.modifiers else { return "" }
    var optionNames = [String]()
    for modifier in modifiers {
        if !modifier.options.isEmpty {
            for options in modifier.options{
                if options.name.uppercased() != "NONE" {
                    optionNames.append(options.name)
                }
            }
        }
    }
    for x in 0..<optionNames.count {
        if x != optionNames.count - 1 {
            text += "\(optionNames[x]), "
        } else {
            text += "\(optionNames[x])"
        }
    }
    return text
}

private func generateSizeLabelFontSize() -> CGFloat {
    return getSize(large: 11, medium: 10, small: 9.5)
}

}

Код из контроллера представления:

override func viewDidLoad() {
    super.viewDidLoad()
    configureNavBar()
    configureTableView()
    getOrders()
    NotificationCenter.default.addObserver(self, selector: #selector(popToRootVC), name: NSNotification.Name(rawValue: "PopToRootVCFromSettingsVC"), object: nil)
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "transactionHistoryCell", for: indexPath) as? TransactionHistoryTableViewCell else { getOrders(); return UITableViewCell() }
    if let lineItem = orders[indexPath.section].lineItems?[indexPath.row] {
        cell.setup(lineItem)
    }
    return cell
}

private func getOrders() {
    let service = TransactionService()
    service.getTransactionData(completion: { (orders) in
        guard let orders = orders else { self.handleNoOrderHistory(); return }
        let filteredOrders = orders.filter{ $0.status == "NEW" || $0.status == "IN_PROGRESS" || $0.status == "READY" || $0.status == "COMPLETE" }
        if filteredOrders.isEmpty {
            DispatchQueue.main.async {
                self.handleNoOrderHistory()
                return
            }
        } else {
            DispatchQueue.main.async {
                self.orders = filteredOrders.sorted{ $0.date > $1.date }
                self.noOrdersView.isHidden = true
                self.tableView.reloadData()
            }
        }
    })
}

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

func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    return 85
}

Компилятор выдает такие предупреждения:

Unable to simultaneously satisfy constraints.
    Probably at least one of the constraints in the following list is one you don't want. 
    Try this: 
        (1) look at each constraint and try to figure out which you don't expect; 
        (2) find the code that added the unwanted constraint or constraints and fix it. 
    (Note: If you're seeing NSAutoresizingMaskLayoutConstraints that you don't understand, refer to the documentation for the UIView property translatesAutoresizingMaskIntoConstraints) 
(
    NSAutoresizingMaskLayoutConstraint:0x600001e972a0 h=--& v=--& UILabel:0x7f9a0050b780.midY == 0   (active),
    NSAutoresizingMaskLayoutConstraint:0x600001e97610 h=--& v=--& UILabel:0x7f9a0050b780.height == 0   (active),
    NSLayoutConstraint:0x600001e8bca0 V:|-(5)-[UILabel:0x7f9a0050b490'5\" Focaccia Everything']   (active, names: '|':UIView:0x7f9a0050b2b0 ),
    NSLayoutConstraint:0x600001d63660 UILabel:0x7f9a0050b490'5\" Focaccia Everything'.bottom == UILabel:0x7f9a0050b780.top - 3   (active)
)

Will attempt to recover by breaking constraint 
NSLayoutConstraint:0x600001d63660 UILabel:0x7f9a0050b490'5" Focaccia Everything'.bottom == UILabel:0x7f9a0050b780.top - 3   (active)

Ответы [ 3 ]

0 голосов
/ 10 мая 2019

Когда вы используете динамическую высоту для построения таблицы и получаете предупреждение об ограничении в консоли, как это, это всегда потому, что приложение не может получить текущую высоту из вашего заданного ограничения.

Самая важная вещь для использования динамической высоты с ячейкой, это то, что вам нужно дать правильное ограничение по вертикали сверху вниз, для ячейки сбора, вам нужно дать правильное ограничение по горизонтали и вертикали.

Например, мне нужно показать три метки в одной ячейке. как это

--------------------------
    LABLE_1
    LABEL_2
    LABEL_3   
--------------------------

Нам нужно добавить

  • LABEL_1 с видом сверху
  • Верх LABEL_2 с низом LABEL_1
  • Верх LABEL_3 с низом LABEL_2
  • Дно LABEL_3 с дном вида

И еще один момент: какой-то компонент пользовательского интерфейса может сам регулировать высоту, например, UIButton, UILabel и т. Д., Поэтому, если вы просто хотите показывать контент, вам не нужно устанавливать ограничение высоты для какого-либо компонента. и если вам нужно это сделать, вы можете изменить приоритет ограничения на 999, это всегда может исправить предупреждение.

Причина, которую я понимаю, заключается в том, что если вы хотите использовать динамическую высоту, компонент должен сам определять высоту, поэтому мы даем табличному виду оценки RowHeight и некоторые ограничения относительно отношений между компонентами. если вам действительно нужно задать ограничение по высоте, используйте приоритет ограничения.

Последняя точка - если компонент не может регулировать высоту сам по себе, например, UIView, вы можете задать ограничение высоты и изменить приоритет высоты или задать ограничение top, bottom с другими, а некоторые компоненты, которые он включает, могут самостоятельно регулировать высоту, а некоторые компонент имеет правильное ограничение по вертикали с представлением

0 голосов
/ 10 мая 2019

Мне пришлось изменить heightForRowAt с автоматического размера на:

func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    //return UITableView.automaticDimension
    guard let lineItem = self.orders[indexPath.section].lineItems?[indexPath.row] else { return 0 }
    let fontSize = getSize(large: 14, medium: 13.5, small: 12)
    guard let topFont = UIFont(name: AppFont.secondary.name, size: fontSize) else { return 0 }
    let heightForTopLabel = heightForView(text: lineItem.name, font: topFont, width: 195)
    let text = returnText(lineItem)
    let bottomFontSize = getSize(large: 11, medium: 10.5, small: 9.5)
    guard let font = UIFont(name: AppFont.secondary.name, size: bottomFontSize) else { return 0 }
    let heightForBottomLabel = heightForView(text: text, font: font, width: 200)
    let padding = getSize(large: 27.5, medium: 14, small: 21)
    let height = heightForTopLabel + heightForBottomLabel + padding
    return height
}

func heightForView(text:String, font:UIFont, width:CGFloat) -> CGFloat{
    let label:UILabel = UILabel(frame: CGRect(x: 0, y: 0, width: width, height: CGFloat.greatestFiniteMagnitude))
    label.numberOfLines = 0
    label.lineBreakMode = NSLineBreakMode.byWordWrapping
    label.font = font
    label.text = text
    label.sizeToFit()
    return label.frame.height
}

private func returnText(_ menuItem: MenuItem) -> String {
    var text = ""
    guard let modifiers = menuItem.modifiers else { print("modifiers are nil"); return "" }
    if modifiers.isEmpty && menuItem.quantity == 1 {
        text = ""
    } else if !modifiers.isEmpty && menuItem.quantity == 1 {
        text = generateModifierText(menuItem)
    } else if !modifiers.isEmpty && menuItem.quantity > 1 {
        let theText = generateModifierText(menuItem)
        text = "\(theText); Quantity: \(menuItem.quantity)"
    } else {
        text = "Quantity: \(menuItem.quantity)"
    }
    return text
}

private func generateModifierText(_ menuItem: MenuItem) -> String {
    var text = ""
    guard let modifiers = menuItem.modifiers else { return "" }
    var optionNames = [String]()
    for modifier in modifiers {
        if !modifier.options.isEmpty {
            for options in modifier.options{
                if options.name.uppercased() != "NONE" {
                    optionNames.append(options.name)
                }
            }
        }
    }
    for x in 0..<optionNames.count {
        if x != optionNames.count - 1 {
            text += "\(optionNames[x]), "
        } else {
            text += "\(optionNames[x])"
        }
    }
    return text
}
0 голосов
/ 10 мая 2019

Проблема в том, что за до вы добавляете любое подпредставление и применяете ограничения, вам нужно установить для translatesAutoresizing... значение false.

Итак, вы звоните configureItemNameLabel и добавляете sizeLabel, перед , вы звоните configureSizeLabel и исправляете его translatesAutoresizing....

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...