Странный эффект растяжения при анимации вложенного представления до скрытого в UIStackView

#ios #swift #uitableview #uistackview

#iOS #swift #uitableview #uistackview

Вопрос:

Я пытаюсь создать UITableView скрытое вложенное представление внизу, которое будет открываться при нажатии на ячейку. У меня есть следующий демонстрационный код:

 class ViewController: UIViewController {
    
    let tableView = UITableView()

    override func viewDidLoad() {
        super.viewDidLoad()
        
        
        view.addSubview(tableView)
        tableView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
            tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            tableView.topAnchor.constraint(equalTo: view.topAnchor),
            tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor)
        ])
        
        tableView.separatorStyle = .none
        tableView.register(ExpandTableCell.self, forCellReuseIdentifier: "Cell")
        tableView.dataSource = self
        tableView.delegate = self
    }

}

extension ViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")
        return cell ?? UITableViewCell()
    }
    
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }
}

extension ViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        guard let cell = tableView.cellForRow(at: indexPath) as? ExpandTableCell else { return }
        tableView.performBatchUpdates({ cell.animate() }, completion: nil)
    }
}
 

И ячейка:

 class ExpandTableCell: UITableViewCell {

    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        setup()
    }

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

    private func setup() {
        setupViews()
    }
    
    private let blueView = UIView()
    
    // MARK: - Views
    
    private func setupViews() {
        selectionStyle = . none
        
        let titleLabel  = UILabel()
        titleLabel.text = "Some Title"
        
        let subtitleLabel = UILabel()
        subtitleLabel.text = "Some othere sdfhdslkjl dsfljdslfj sdlj sdfldsjfldsjf sdfjdslfjds"
        subtitleLabel.numberOfLines = 2
        
        blueView.backgroundColor = .blue
        blueView.translatesAutoresizingMaskIntoConstraints = false
        blueView.heightAnchor.constraint(equalToConstant: 50.0).isActive = true
        
        let stackView = UIStackView(arrangedSubviews: [titleLabel, subtitleLabel, blueView])
        stackView.axis = .vertical
        stackView.spacing = 8.0
        
        blueView.isHidden = true
        
        addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            stackView.topAnchor.constraint(equalTo: topAnchor),
            stackView.leadingAnchor.constraint(equalTo: leadingAnchor),
            stackView.trailingAnchor.constraint(equalTo: trailingAnchor),
            stackView.bottomAnchor.constraint(equalTo: bottomAnchor)
        ])
    }
    
    func animate() {
        UIView.animate(withDuration: 0.1, animations: { [blueView] in
            blueView.isHidden.toggle()
        })
    }

}
 

Проблема в том, что анимация имеет следующий эффект:

введите описание изображения здесь

Он сжимает содержимое метки над ним. Он должен просто скользить вниз снизу.

Что я здесь делаю не так?

Комментарии:

1. Попробуйте изменить продолжительность анимации на 0.3 … в качестве примечания, убедитесь, что вы добавляете и ограничиваете вложенные представления в ячейку contentView , а не в саму ячейку.

Ответ №1:

Просто измените время анимации, чтобы оно соответствовало времени просмотра таблицы. Попробуйте 0.3

     func animate() {
        UIView.animate(withDuration: 0.3, animations: { [blueView] in
            blueView.isHidden.toggle()
        })
    }
 

Артефакт исчез.

Комментарии:

1. Еще одна деталь: вы должны добавить свой вид стека в ячейку contentView , а не в саму ячейку. В противном случае вы можете столкнуться с проблемами позже.