使用可扩展的Tableview单元格和dequeueReusableCells

时间:2019-12-09 17:56:34

标签: ios swift uitableview

我已经建立了一个简单的项目来快速测试各种TableView功能,尤其是启用可扩展单元。

我已经使用了可扩展单元格,在该项目中,第一个单元格包含一个标签,该标签显示了今天的日期。单击时,将展开包含DatePicker的单元格。但是我注意到动画的效果有些奇怪的现象:

  1. 当单元格第一次扩展时,从单元格11开始,它会滑过以下单元格(12、13、14等)的顶部。然后以相同的方式收缩。

  2. 单元格第二次扩展时,它按预期方式工作,将所有单元格向下推,但是收缩时,其行为与第一种情况相同,从单元格11滑到编号较高的单元格顶部

  3. 如果我双击第一个单元格,则datePicker几乎立即消失(使空白单元格收缩)。

对以上内容的任何见解将不胜感激。

我将所有奇数单元格的背景设置为蓝色,动画速度设置为2秒,以帮助查看问题。

谢谢。

TableViewController

import UIKit

protocol DateLabelDelegate: AnyObject {
    func setDateLabel(_ text: String)
}

protocol DatePickerVisibilityDelegate: AnyObject {
    func showCell(cellExpanded: Bool)
}

class TableViewController: UITableViewController {
    var dateCellExpanded: Bool = false
    var date: String = String()
    let todayDate = Date()
    let formatter = DateFormatter()

    weak var dateLabelDelegate: DateLabelDelegate?
    weak var datePickerVisibilityDelegate: DatePickerVisibilityDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()

        tableViewSetup()
        formatter.dateFormat = "dd.MM.yyyy"
        let result = formatter.string(from: todayDate)
        date = "Date: \(result)"
    }

    func tableViewSetup() {
        // Format tableView
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 200
        tableView.tableFooterView = UIView(frame: CGRect.zero) // Removes Empty Cells
        tableView.separatorStyle = UITableViewCell.SeparatorStyle.none

        // Register Cells
        tableView.register(UINib(nibName: "DatePickerCell", bundle: nil), forCellReuseIdentifier: "DatePickerCell")
        tableView.register(UINib(nibName: "DateLabelCell", bundle: nil), forCellReuseIdentifier: "DateLabelCell")
        tableView.register(UINib(nibName: "SampleTableViewCell", bundle: nil), forCellReuseIdentifier: "SampleTableViewCell")
    }

    // MARK: - Table view data source

    override func numberOfSections(in _: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_: UITableView, numberOfRowsInSection _: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return 50
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.row == 0 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "DateLabelCell", for: indexPath) as! DateLabelCell
            cell.setDateLabel(date)
            return cell

        } else if indexPath.row == 1 {
            let cell = tableView.dequeueReusableCell(withIdentifier: "DatePickerCell", for: indexPath) as! DatePickerCell
            cell.dateDelegate = self
            cell.showCell(cellExpanded: dateCellExpanded)

            return cell

        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: "SampleTableViewCell", for: indexPath) as! SampleTableViewCell
            cell.label.text = "Cell \(indexPath.row)"
            if indexPath.row % 2 == 0 {
                cell.backgroundColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
            } else {
                cell.backgroundColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
            }
            return cell
        }
    }

    override func tableView(_: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        // Expands and contracts DatePicker Cell
        if indexPath.row == 1 {
            if dateCellExpanded {
                return 250
            } else {
                return 0
            }
        }
        return 50
    }

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        if indexPath.row == 0 {
            if dateCellExpanded {
                dateCellExpanded = false
            } else {
                dateCellExpanded = true
            }
            UIView.animate(withDuration: 2, animations: { () -> Void in
                tableView.beginUpdates()
                tableView.reloadRows(at: [IndexPath(row: 1, section: 0)], with: .none)
                tableView.endUpdates()
            })
        }
    }
}

extension TableViewController: DatePickerDelegate {
    func setDate(_ text: String) {
        date = "Date: \(text)"
        tableView.reloadRows(at: [IndexPath(row: 0, section: 0)], with: .automatic)
    }
}

DatePickerCell

import UIKit

protocol DatePickerDelegate: AnyObject {
    func setDate(_ text: String)
}

class DatePickerCell: UITableViewCell {
    weak var dateDelegate: DatePickerDelegate?

    var isHiddenState = true

    @IBOutlet var datePicker: UIDatePicker!
    let formatter = DateFormatter()

    override func awakeFromNib() {
        super.awakeFromNib()
        formatter.dateFormat = "dd.MM.yyyy"
        isHidden = isHiddenState
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }

    override func prepareForReuse() {}

    @IBAction func datePickerDidChange(_: Any) {
        let result = formatter.string(from: datePicker.date)
        print("RESULT -> \(result)")
        dateDelegate?.setDate(result)
    }
}

extension DatePickerCell: DatePickerVisibilityDelegate {
    func showCell(cellExpanded: Bool) {
        isHidden = !cellExpanded
        print("InDatePicker showCell() --> isHiddenState = \(isHiddenState)")
    }
}

DateLabelCell

import UIKit

class DateLabelCell: UITableViewCell {
    @IBOutlet var dateLabel: UILabel!

    // let sendingTableVC = TableViewController()

    override func awakeFromNib() {
        super.awakeFromNib()
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)
    }
}

extension DateLabelCell: DateLabelDelegate {
    func setDateLabel(_ text: String) {
        dateLabel.text = text
    }
}

SampleTableViewCell

import UIKit

class SampleTableViewCell: UITableViewCell {
    @IBOutlet var label: UILabel!
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
}

0 个答案:

没有答案