swift弹出窗方案

2021-12-03  本文已影响0人  迷路的小小
  1. 窗口协议
public protocol PickerViewProtol: UIView {
    
    var picker: BWeakPickerProtocol? { get set }
    var start: BAnimationsProtocol { get }
    var end: BAnimationsProtocol { get }
    
    func layout(in viewController: UIViewController)
}

public extension PickerViewProtol {
    var start: BAnimationsProtocol {
        return AlertStartAnimations(self)
    }
    
    var end: BAnimationsProtocol {
        return AlertEndAnimations(self)
    }
    
    func layout(in viewController: UIViewController) {}
}
  1. 动画协议
public protocol BAnimationsProtocol {
    var alpha: CGFloat { get }
    var transform: CGAffineTransform { get }
    var origin: CGPoint { get }
    var duration: TimeInterval { get }
    
    init(_ view: UIView)
}

public extension BAnimationsProtocol {
    
    var duration: TimeInterval {
        return 0.1
    }
    
    var origin: CGPoint { .zero }
}
  1. 弹出窗主题协议
public protocol BWeakPickerProtocol {
    func hide(completion: (() -> Void)?) -> Void
}
  1. 弹出窗实现
public struct SheetStartAutoAnimations: BAnimationsProtocol {
    public var alpha: CGFloat
    
    public var transform: CGAffineTransform
        
    public let duration: TimeInterval = 0.3
    
    weak var view: UIView?
    
    public init(_ view: UIView) {
        self.view = view
        
        transform = .identity.translatedBy(x: 0, y: view.frame.height)
        alpha = 1
    }
}

public struct SheetEndAutoAnimations: BAnimationsProtocol {
    public var alpha: CGFloat
    
    public var transform: CGAffineTransform
        
    public let duration: TimeInterval = 0.3
    
    weak var view: UIView?
    
    public init(_ view: UIView) {
        self.view = view
        
        transform = .identity
        alpha = 1
    }
}
public class JBPopupViewController<Content: PickerViewProtol>: UIViewController {
    private let content: Content
    private var isShow: Bool = false

    public init(_ content: Content) {
        self.content = content

        super.init(nibName: nil, bundle: nil)
        modalPresentationStyle = .overCurrentContext
        view.backgroundColor = UIColor(white: 0, alpha: 0.3)

        view.addSubview(content)
        content.picker = self
        content.layout(in: self)
    }

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

    override public func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }
    
    public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
        super.touchesBegan(touches, with: event)
        
        guard let point = touches.first?.location(in: view) else { return }
        
        if !content.frame.contains(point) {
            hide(completion: nil)
        }
    }

    public func show(in viewController: UIViewController) {
        viewController.present(self, animated: false) { [self] in
            isShow = true
            
            content.transform = content.start.transform
            content.alpha = content.start.alpha
            
            UIView.animate(withDuration: content.start.duration) {
                content.transform = content.end.transform
                content.alpha = content.end.alpha
            }
        }
        
    }
}

extension JBPopupViewController: BWeakPickerProtocol {
    public func hide(completion: (() -> Void)?) {
        content.transform = content.end.transform
        content.alpha = content.end.alpha

        UIView.animate(withDuration: content.end.duration) { [self] in
            content.transform = content.start.transform
            content.alpha = content.start.alpha
        } completion: { [self] finish in
            guard finish else { return }
            isShow = false
            dismiss(animated: false, completion: completion)
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读