tableHeaderView高度自适应,可当LinearLayout使用

394 阅读1分钟

非常简单的tableHeaderView高度自适应

代码量少, 效果好, 而且可以当LinearLayout使用

aa.gif

详细代码demo: github.com/AblerSong/L…


   
    lazy var stackView = {
        LinearLayoutView(tableView: tableView)
    }()



    func testUI() {
        for i in 0...100 {
            let label = UILabel()
            label.text = "\(i)"
            label.backgroundColor = .random
            stackView.addArrangedSubview(label)
            if i == 10 {
                let v = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 200))
                stackView.addArrangedSubview(v)
                NSLayoutConstraint.activate([
                    v.heightAnchor.constraint(equalToConstant: 100)
                ])
            }
        }
        DispatchQueue.main.asyncAfter(deadline:.now() + 2) {
            let v = UIButton(type: .system)
            v.backgroundColor = .random
            self.stackView.addArrangedSubview(v)
            NSLayoutConstraint.activate([
                v.heightAnchor.constraint(equalToConstant: 500)
            ])
        }
    }



class LinearLayoutView: UIView {
    convenience init(tableView: UITableView, edgeInsets: UIEdgeInsets = .zero) {
        self.init()
        NSLayoutConstraint.activate([
            stackView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: edgeInsets.left),
            stackView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -edgeInsets.right),
            stackView.topAnchor.constraint(equalTo: self.topAnchor, constant: edgeInsets.top),
            stackView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -edgeInsets.bottom)
        ])
        
        self.tableView = tableView
        self.tableView!.tableHeaderView = self
        NSLayoutConstraint.activate([
            self.widthAnchor.constraint(equalTo: self.tableView!.widthAnchor),
        ])
    }
    
    private weak var tableView: UITableView?
    
    private var workItem: DispatchWorkItem?
    
    private func performDelayedAction(after delay: TimeInterval = 0.09, action: @escaping () -> Void) {
        workItem?.cancel()
        let newWorkItem = DispatchWorkItem { action() }
        workItem = newWorkItem
        DispatchQueue.main.asyncAfter(deadline:.now() + delay, execute: newWorkItem)
    }
    
    func addArrangedSubview(_ view: UIView) {
        stackView.addArrangedSubview(view)
    }
    
    func removeArrangedSubview(_ view: UIView) {
        stackView.removeArrangedSubview(view)
        view.removeFromSuperview()
    }
    
    override func layoutSubviews() {
        super.layoutSubviews()
        performDelayedAction() { [unowned self] in
            self.refreshUI()
        }
    }
    
    @MainActor
    private func refreshUI() {
        tableView?.tableHeaderView = self
    }
    
    lazy var stackView = {
        let stack = UIStackView()
        stack.backgroundColor = .white
        stack.axis = .vertical
        stack.translatesAutoresizingMaskIntoConstraints = false
        return stack
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .white
        translatesAutoresizingMaskIntoConstraints = false
        
        addSubview(stackView)
    }
    
    required init(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}