iOS 自定义可拖拽 panel

gif.gif

自定义屏幕相关常量

import Foundation
import UIKit

struct JLScreen {
    
    static var width: CGFloat {
        return UIScreen.main.bounds.width
    }
    
    static var height: CGFloat {
        return UIScreen.main.bounds.height
    }
    
    static var status_navi_height: CGFloat {
        return UIApplication.shared.statusBarFrame.height + 44
    }
}

可以进一步封装, 将 tableVeiw 剥离出来

import UIKit

class JLPanel: UIView {

    enum JLPanelPosition {
        case bottom, middle, top
    }
       
    private let TOP_Y: CGFloat = JLScreen.status_navi_height + 20
    
    private let MIDDLE_Y: CGFloat = JLScreen.height * 0.5

    private let BOTTOM_Y: CGFloat = JLScreen.height

    private let threshold: CGFloat = 100
    
    var position: JLPanelPosition = .middle {
        didSet {
            if position == .top {
                self.tableView.isScrollEnabled = true
            } else {
                self.tableView.isScrollEnabled = false
            }
        }
    }
    
    lazy var tableView: UITableView = {
        let tableView = UITableView()
        tableView.delegate = self
        tableView.dataSource = self
        tableView.isScrollEnabled = false
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
        return tableView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: CGRect(x: 0, y: MIDDLE_Y, width: JLScreen.width, height: JLScreen.height - TOP_Y))
        let panGesture: UIPanGestureRecognizer = UIPanGestureRecognizer()
        panGesture.delegate = self
        panGesture.addTarget(self, action: #selector(handlePanGesture(_:)))
        backgroundColor = .purple
        isUserInteractionEnabled = true
        layer.cornerRadius = 20
        layer.masksToBounds = true
        addGestureRecognizer(panGesture)
        addSubview(tableView)
        tableView.snp.makeConstraints { (make) in
            make.top.equalTo(30)
            make.left.right.bottom.equalToSuperview()
        }
    }
    
    @objc private func handlePanGesture(_ sender: UIPanGestureRecognizer) {
        let point = sender.translation(in: self)
        if sender.state == .began {
        } else if sender.state == .changed {
            if self.position == .top {
                if point.y > 0 {
                    self.frame.origin.y = TOP_Y + point.y
                }
            } else if self.position == .middle {
                if self.frame.origin.y >= TOP_Y {
                    self.frame.origin.y = self.MIDDLE_Y + point.y
                }
            } else if self.position == .bottom {
                
            }
        } else if sender.state == .ended {
            if self.position == .top {
                if point.y > self.MIDDLE_Y - self.TOP_Y {
                    UIView.animate(withDuration: 0.2) {
                        self.frame.origin.y = JLScreen.height
                    } completion: { (_) in
                        self.position = .bottom
                    }
                } else if point.y > threshold  {
                    UIView.animate(withDuration: 0.2) {
                        self.frame.origin.y = self.MIDDLE_Y
                    } completion: { (_) in
                        self.position = .middle
                    }
                } else {
                    UIView.animate(withDuration: 0.2) {
                        self.frame.origin.y = self.TOP_Y
                    } completion: { (_) in
                        self.position = .top
                    }
                }
            } else if self.position == .middle {
                if point.y > threshold {
                    UIView.animate(withDuration: 0.2) {
                        self.frame.origin.y = JLScreen.height
                    } completion: { (_) in
                        self.position = .bottom
                    }
                } else if point.y > 0 || point.y >= -threshold {
                    UIView.animate(withDuration: 0.2) {
                        self.frame.origin.y = self.MIDDLE_Y
                    } completion: { (_) in
                        self.position = .middle
                    }
                } else if point.y < -threshold {
                    UIView.animate(withDuration: 0.2) {
                        self.frame.origin.y = self.TOP_Y
                    } completion: { (_) in
                        self.position = .top
                    }
                }
            }
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
}

extension JLPanel: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 25
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
        cell.textLabel?.text = "\(indexPath.row)"
        return cell
    }
}

extension JLPanel: UIGestureRecognizerDelegate {
    func gestureRecognizer(_ gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWith otherGestureRecognizer: UIGestureRecognizer) -> Bool {
        return false
    }
}

猜你喜欢

转载自blog.csdn.net/LeeCSDN77/article/details/109701432