Запутался в попытке понять .layoutMarginsGuide внутри пользовательского раздела Заголовок для табличного представления - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь создать пользовательский заголовок раздела для табличного представления, содержащего textView. Я создал простое приложение, адаптируясь из учебника. Это создает рабочий пример. Однако, когда я перемещаю код в мое производственное приложение, он не размещается правильно. Простое учебное приложение создает макет из nib (без Main.storyboard), а производственное приложение - нет. Я предполагаю, что это является частью проблемы. В обоих я использую .layoutMarginsGuide.

Код следует из дизайна пользовательского заголовка.

class TextViewHeader: UITableViewHeaderFooterView {
static let reuseIdentifer = "TextViewHeaderReuseIdentifier"

let sectionTextView = UITextView.init()

override public init(reuseIdentifier: String?) {
    super.init(reuseIdentifier: reuseIdentifier)

    sectionTextView.font = UIFont.preferredFont(forTextStyle: .title2)
    sectionTextView.textColor = UIColor.blue
    sectionTextView.backgroundColor = UIColor.yellow
    sectionTextView.translatesAutoresizingMaskIntoConstraints = false

    self.contentView.addSubview(sectionTextView)
    let margins = contentView.layoutMarginsGuide
    sectionTextView.isScrollEnabled = false
    //sectionTextView.text = "Something"
    sectionTextView.frameLayoutGuide.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
    sectionTextView.frameLayoutGuide.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
    sectionTextView.frameLayoutGuide.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
    sectionTextView.frameLayoutGuide.bottomAnchor.constraint(equalTo: margins.bottomAnchor).isActive = true
}

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

Обратите внимание, что макет определяется:

 let margins = contentView.layoutMarginsGuide

И для простоты отслеживания размеров и размещения TextView я установил желтый фон.

  sectionTextView.backgroundColor = UIColor.yellow

Требуется дополнительное программирование для регистрации заголовка в viewDidLoad, что я и сделал:

   override func viewDidLoad() {
    super.viewDidLoad()
    self.view.backgroundColor = UIColor.white
    self.tableView.frame = self.view.bounds
    self.tableView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    self.tableView.dataSource = self
    self.tableView.delegate = self
    self.tableView.register(TextViewHeader.self, forHeaderFooterViewReuseIdentifier: TextViewHeader.reuseIdentifer)
    self.view.addSubview(self.tableView)
    self.tableView.rowHeight = UITableViewAutomaticDimension
    self.tableView.estimatedRowHeight = 300
}

И заменить:

   tableView(_ tableView:, titleForHeaderInSection section:).

со следующим:

   func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    guard let header = tableView.dequeueReusableHeaderFooterView(withIdentifier: TextViewHeader.reuseIdentifer) as? TextViewHeader else {
        return nil
    }
    header.customTextView.text = "Section \(section + 1)"
    return header
    }

Это работает и вставляет textView с макетом, как и ожидалось.

enter image description here

Однако, похоже, этого не происходит при переносе программирования в мое производственное приложение. В этом случае я объединяю этот программный макет с макетом в конструкторе интерфейса xcode. Что-то мешает макету.

В производственном приложении я использую подобный код в пользовательском дизайне заголовка. (включено ниже для полноты)

class TextViewHeader: UITableViewHeaderFooterView {
static let reuseIdentifer = "TextViewHeaderReuseIdentifier"

let sectionTextView = UITextView.init()

override public init(reuseIdentifier: String?) {
    super.init(reuseIdentifier: reuseIdentifier)

    sectionTextView.font = UIFont.preferredFont(forTextStyle: .title2)
    sectionTextView.textColor = UIColor.blue
    sectionTextView.backgroundColor = UIColor.yellow
    sectionTextView.translatesAutoresizingMaskIntoConstraints = false

    self.contentView.addSubview(sectionTextView)
    let margins = contentView.layoutMarginsGuide
    sectionTextView.isScrollEnabled = false
    //sectionTextView.text = "Something"
    sectionTextView.frameLayoutGuide.leadingAnchor.constraint(equalTo: margins.leadingAnchor).isActive = true
    sectionTextView.frameLayoutGuide.trailingAnchor.constraint(equalTo: margins.trailingAnchor).isActive = true
    sectionTextView.frameLayoutGuide.topAnchor.constraint(equalTo: margins.topAnchor).isActive = true
    sectionTextView.frameLayoutGuide.bottomAnchor.constraint(equalTo: margins.bottomAnchor).isActive = true
}

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

Это дает следующий макет.

enter image description here

Просмотр раздела tableView моей раскадровки. Я вижу настройку «Высота заголовка раздела», которая установлена ​​в автоматический режим, а «Оценка высоты строки» установлена ​​в ноль. Изменение этой сметы для автоматизации приводит к изменению результатов:

Настройки: enter image description here

И полученный заголовок выглядит так:

improved result

Лучше, но пространство над textView слишком велико.

Пытаясь исследовать, я вижу следующее после перерыва.

the margins

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

Однако при расследовании на этом перерыве я получаю следующие предупреждения:

2018-11-14 15: 21: 54.086637-0500 appName [31946: 1780119] [LayoutConstraints] Невозможно одновременно удовлетворить ограничения. Вероятно, по крайней мере одно из ограничений в следующем списке ты не хочешь Попробуйте это: (1) посмотреть на каждое ограничение и попытаться выяснить, чего вы не ожидаете; (2) найти код, который добавил нежелательное ограничение или ограничения и исправление.

Далее следует список нескольких ограничений, касающихся , ведущих и , трейлинг , но не top и bottom . Поэтому нет четких указаний на то, что нужно исправить.

Вот перечисленные ограничения

 "<NSLayoutConstraint:0x600002364280 UILayoutGuide:0x6000039257a0'UIScrollView-frameLayoutGuide'.leading == UILayoutGuide:0x60000397a060'UIViewLayoutMarginsGuide'.leading   (active)>",
"<NSLayoutConstraint:0x6000023642d0 UILayoutGuide:0x6000039257a0'UIScrollView-frameLayoutGuide'.trailing == UILayoutGuide:0x60000397a060'UIViewLayoutMarginsGuide'.trailing   (active)>",
"<NSLayoutConstraint:0x60000231b840 'UIView-Encapsulated-Layout-Width' _UITableViewHeaderFooterContentView:0x7fe43a815410.width == 0   (active)>",
"<NSLayoutConstraint:0x60000231b4d0 'UIView-leftMargin-guide-constraint' H:|-(8)-[UILayoutGuide:0x60000397a060'UIViewLayoutMarginsGuide'](LTR)   (active, names: '|':_UITableViewHeaderFooterContentView:0x7fe43a815410 )>",
 "<NSLayoutConstraint:0x60000231b570 'UIView-rightMargin-guide-constraint' H:[UILayoutGuide:0x60000397a060'UIViewLayoutMarginsGuide']-(8)-|(LTR)   (active, names: '|':_UITableViewHeaderFooterContentView:0x7fe43a815410 )>"

Моя единственная мысль - это смешивание "leftMargin" и "rightMargin" и ".leading" и ".trailing". Возможно ли в этом проблема? Но, как уже говорилось, проблема заключается в выравнивании сверху и снизу.

Мой обзор настроек раскадровки для tableView и заголовков tableView не дает никакой дополнительной информации о возможных конфликтах.

Чего мне не хватает?

1 Ответ

0 голосов
/ 18 ноября 2018

Я считаю, что это проблемный подход. Проблемы NSLayoutConstraint в настоящее время мне не известны. Кажется, это обусловлено временными событиями. Кроме того, есть некоторые обсуждения, что это несколько глючит. См. Следующее: Что такое NSLayoutConstraint "UIView-Encapsulated-Layout-Height" и как мне заставить его пересчитывать чисто?

Я решил отказаться от использования tableView.dequeueReusableHeaderFooterView. Количество секций будет ограничено (2 или 3, в огромном количестве для использования), поэтому затраты будут минимальными.

Поэтому я реализовал простой метод.

   //define size of font to use 
let sectionFont = UIFont.preferredFont(forTextStyle: .title3)
let fontsize = UIFont.preferredFont(forTextStyle: .title3).pointSize

override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let headerView = UIView.init(frame: CGRect.init(x: 0, y: 0, width: tableView.frame.width, height: fontsize+10))
    let textView = UITextView()
    textView.frame = CGRect.init(x: 0, y: -10, width: headerView.frame.width-10, height: headerView.frame.height-0)
    textView.text = "Section \(section)"
    textView.font = sectionFont

    headerView.addSubview(textView)

    return headerView
}


override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return fontsize+10
}
...