Многоразовый UITableHeaderFooterView Свободное состояние ориентации ImageView - PullRequest
0 голосов
/ 31 января 2019

У меня есть расширяемый UITableView с определенной высотой ячейки, верхнего и нижнего колонтитула.Когда пользователь нажимает на заголовок, под ним начинают показываться ячейки (развернуть раздел).Когда пользователь снова нажмет, раздел свернется.

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

На рисунке ниже, цвет заголовка Нью-Йоркавыглядит хорошо, но ориентация стрелы неверна.Также Манхэттен, заголовок расширен, но не получает зеленый цвет и правильную UIImageView ориентацию.

PS: Я знаю, что об этом спрашивали много раз, но я не могу понятькакой из них правильный.

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

protocol ExpandableHeaderViewDelegate {
func toggleSection(header: DistrictTableViewHeader, section: Int)
}

class DistrictTableViewHeader: UITableViewHeaderFooterView {
var delegate: ExpandableHeaderViewDelegate?
var section: Int!

let nameLabel: UILabel = {
   let l = UILabel()
    l.textColor = Color.DistrictsPage.headerTextColor
    return l
}()

private let arrowImage: UIImageView = {
  let i = UIImageView()
    let image = UIImage(named: "ileri")?.withRenderingMode(UIImage.RenderingMode.alwaysTemplate)
    i.image = image
    i.contentMode = .scaleAspectFit
    return i
}()
var isColapsed: Bool!{
    didSet{
        layoutSubviews()
    }
}

override init(reuseIdentifier: String?) {

    super.init(reuseIdentifier: reuseIdentifier)
    self.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(selectHeaderAction)))
    nameLabel.translatesAutoresizingMaskIntoConstraints = false
    nameLabel.font = UIFont.systemFont(ofSize: 22)
    nameLabel.textColor = Color.DistrictsPage.headerTextColor
    contentView.addSubview(nameLabel)
    nameLabel.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
    nameLabel.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 15).isActive = true

    arrowImage.tintColor =  UIColor(red:0.32, green:0.36, blue:0.36, alpha:1.0)
    arrowImage.translatesAutoresizingMaskIntoConstraints = false
    contentView.addSubview(arrowImage)
    arrowImage.centerYAnchor.constraint(equalTo: contentView.centerYAnchor).isActive = true
    arrowImage.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20).isActive = true
    arrowImage.widthAnchor.constraint(equalToConstant: 20).isActive = true

}

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

@objc func selectHeaderAction(gestureRecognizer: UITapGestureRecognizer) {
    let cell = gestureRecognizer.view as! DistrictTableViewHeader
    self.isColapsed = !isColapsed
    if(!isColapsed){
        let degrees : Double = 90 //the value in degrees
        UIView.animate(withDuration: 0.5) { [weak self] in
            self?.nameLabel.textColor = Color.Common.garantiLightGreen
            self?.arrowImage.tintColor = Color.Common.garantiLightGreen
            self?.arrowImage.rotate(CGFloat(degrees * .pi/180))
            self?.contentView.backgroundColor = UIColor(red:0.97, green:0.97, blue:0.97, alpha:1.0)
        }
    }else{
        let degrees : Double = 0 //the value in degrees
        UIView.animate(withDuration: 0.5) { [weak self] in
            self?.nameLabel.textColor = Color.DistrictsPage.headerTextColor
            self?.arrowImage.tintColor = UIColor.black
            self?.arrowImage.rotate(CGFloat(degrees * .pi/180))
            self?.contentView.backgroundColor = UIColor.white
        }
    }
    delegate?.toggleSection(header: self, section: cell.section)
}

func customInit(title: String, section: Int, delegate: ExpandableHeaderViewDelegate) {
    self.nameLabel.text = title
    self.nameLabel.accessibilityIdentifier = title
    self.section = section
    self.delegate = delegate
}

override func layoutSubviews() {
    super.layoutSubviews()
    self.contentView.backgroundColor = UIColor.white

}

}

Как инициализировать заголовок:

func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
    return 60
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    let header: DistrictTableViewHeader = tableView.dequeueReusableHeaderFooterView(withIdentifier: headerId) as! DistrictTableViewHeader
    //let header = DistrictTableViewHeader()

    header.isColapsed = !self.cities[section].isExpanded
    header.customInit(title: self.cities[section].name, section: section, delegate: self)
    return header
}

Как развернуть / свернуть:

func toggleSection(header: DistrictTableViewHeader, section: Int) {
    self.cities[section].isExpanded = !self.cities[section].isExpanded
    let contentOffset = self.tableView.contentOffset
    self.tableView.reloadData()

}

РЕДАКТИРОВАТЬ: Для гуру UITableView, я добавил также пример проекта :) Образец Ссылка проекта:

https://github.com/emreond/tableViewLayoutIssue

enter image description here

1 Ответ

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

После снятия с повторного использования представления вы должны сбросить все изменения, которые могли произойти с ним.

В этом случае вы устанавливаете header.isColapsed, но это не сбрасывает все состояния представления, которые ему необходимы.Код изменения состояния представления в selectHeaderAction также должен вызываться при повторном использовании представления.

Для правильной работы потребуется небольшой рефакторинг.Измените установщик isColapse, чтобы он делал больше:

var isColapsed: Bool!{
  didSet{
     if(!isColapsed){
        let degrees : Double = 90 //the value in degrees
        self?.nameLabel.textColor = Color.Common.garantiLightGreen
        self?.arrowImage.tintColor = Color.Common.garantiLightGreen
        self?.arrowImage.rotate(CGFloat(degrees * .pi/180))
        self?.contentView.backgroundColor = UIColor(red:0.97, green:0.97, blue:0.97, alpha:1.0)
     }else{
        let degrees : Double = 0 //the value in degrees
        self?.nameLabel.textColor = Color.DistrictsPage.headerTextColor
        self?.arrowImage.tintColor = UIColor.black
        self?.arrowImage.rotate(CGFloat(degrees * .pi/180))
        self?.contentView.backgroundColor = UIColor.white
      }
      layoutSubviews()
  }
}

И заставьте жест таппера делать меньше:

@objc func selectHeaderAction(gestureRecognizer: UITapGestureRecognizer) {
    let cell = gestureRecognizer.view as! DistrictTableViewHeader
    UIView.animate(withDuration: 0.5) { [weak self] in
        self.isColapsed = !isColapsed
    }
    delegate?.toggleSection(header: self, section: cell.section)
}

Я думаю, это должно исправить.Скажите, если это работает.


Вы делаете вращение неправильно.Добавление CAAnimation это круто, но вы не можете легко отменить его, когда представление используется повторно.Вместо этого просто измените свойство transform и позвольте блоку UIView.animate иметь дело с анимацией на более высоком уровне.

func rotate(_ toValue: CGFloat) {
  self.transform = CGAffineTransform.init(rotationAngle: toValue)
}

Затем вы перезагрузите таблицу, которая отменяет всю анимацию, которую выхочу сделать.

 func toggleSection(header: DistrictTableViewHeader, section: Int) {
    self.cities[section].isExpanded = !self.cities[section].isExpanded
  let count = self.cities[section].districts.count
  let indexPaths:[IndexPath] = (0..<count).map{ IndexPath.init(row: $0, section: section) }
  if self.cities[section].isExpanded {
    self.tableView.insertRows(at: indexPaths, with: .automatic);
  }else{
    self.tableView.deleteRows(at: indexPaths, with: .automatic);
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...