Заголовок таблицы UITableView сбрасывается при свертывании заголовков складных секций - PullRequest
0 голосов
/ 15 января 2019

У меня есть сворачиваемый заголовок для разделов uitableview, основанный на другом сообщении о переполнении стека (не знаю, где сейчас, как это было несколько месяцев назад). Так получилось, что тестеры обнаружили странную ошибку, при которой свертывание всех разделов сводит представление заголовка таблицы вниз.

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

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

Любая помощь будет оценена.

В моем демонстрационном проекте (рад поделиться), когда четыре раздела свернуты, это выглядит так: enter image description here

Когда пользователь раскрывает некоторые разделы, прокручивает заголовок раздела вверху, а содержимое прокручивается под ним, а затем сворачивает закрепленный заголовок раздела, это может выглядеть так: enter image description here

У меня есть протокол для делегата:

protocol CollapsibleHeaderViewDelegate: class {
  func toggleSection(header: CollapsibleSectionHeader, section: Int)
}

protocol SectionHeaderCollapsible {
  var isCollapsed: Bool { get }
  var rowCount: Int { get }
}

И подкласс UITableVieHeaderFooterView:

class CollapsibleHeader: UITableViewHeaderFooterView {

  @IBOutlet var sectionHeaderLabel: UILabel!
  var collapsed = false
  weak var delegate: CollapsibleHeaderViewDelegate?
  var sectionItem: SectionHeaderCollapsible?

  static let reuseIdentifer = "CollapsibleHeader"

  func configure(headerText: String) {
    textLabel?.text = headerText
  }

  override func awakeFromNib() {
    super.awakeFromNib()
    addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(didTapHeader)))
  }

  @objc private func didTapHeader(gestureRecognizer: UITapGestureRecognizer) {
    guard let header = gestureRecognizer.view as? CollapsibleHeader else { return }

    delegate?.toggleSection(header: self, section: header.tag)
  }
}

Тогда делегат делает что-то вроде. это:

struct CollapsibleSection: SectionHeaderCollapsible {
  var isCollapsed: Bool = false
  var rowCount: Int {
    get {
      return isCollapsed ? 0 : dataContents.count
    }
  }
  var dataContents: [String]
}

class ViewController: UIViewController {

  @IBOutlet var tableView: UITableView!
  @IBOutlet var headerView: UITableView!

  var sections = [CollapsibleSection(isCollapsed: false, dataContents: ["first", "second"]),
                  CollapsibleSection(isCollapsed: false, dataContents: ["red", "blue"]),
                  CollapsibleSection(isCollapsed: false, dataContents: ["seven", "five"]),
                  CollapsibleSection(isCollapsed: false, dataContents: ["Josephine", "Edward"])]

  override func viewDidLoad() {
    super.viewDidLoad()
    tableView.dataSource = self
    tableView.delegate = self
    let nib = UINib(nibName: "CollapsibleHeader", bundle: nil)
    tableView.register(nib, forHeaderFooterViewReuseIdentifier: "CollapsibleHeader")
  }
}

extension ViewController: UITableViewDataSource, UITableViewDelegate {
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return sections[section].rowCount
  }

  func numberOfSections(in tableView: UITableView) -> Int {
    return sections.count
  }

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") else { fatalError() }
    cell.textLabel?.text = sections[indexPath.section].dataContents[indexPath.row]
    return cell
  }

  func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    guard let header = self.tableView.dequeueReusableHeaderFooterView(withIdentifier: "CollapsibleHeader") as? CollapsibleHeader else { fatalError() }
    header.sectionHeaderLabel.text = "Section \(section + 1)"
    header.delegate = self
    header.tag = section
    return header
  }

  func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 100
  }
}

extension ViewController: CollapsibleHeaderViewDelegate {
  func toggleSection(header: CollapsibleHeader, section: Int) {
    sections[section].isCollapsed = !sections[section].isCollapsed
    tableView.reloadSections([section], with: .fade)
  }
}

EDIT: Похоже, мои коллеги создали работу, основанную на (или, по крайней мере, похожем) на ваш ответ:

if tableView.contentOffset.y < 0 { 
  var offset = tableView.contentOffset 
  offset.y = tableView.contentSize.height - tableView.bounds.height     
  tableView.setContentOffset(offset, animated: true) 
} else { 
  tableView.setContentOffset(tableView.contentOffset, animated: true) 
}

1 Ответ

0 голосов
/ 21 января 2019

Столкнулся с той же проблемой, по-видимому, сразу после «reloadSections», у tableOf contentOffset.y есть какое-то странное значение (вы можете увидеть это при печати «tableView.contentOffset.y» до и после «reloadSections»). Поэтому я просто устанавливаю contentOffset после его разворачивания на значение смещения 0:

    let offset = tableView.contentOffset.y
    // Reload section
    tableView.reloadSections(IndexSet(integer: section), with: .automatic)

    if !sections[section].isCollapsed {
        tableView.contentOffset.y = offset - offset
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...