在APP生成悬浮窗(Swift版)

4,476 阅读1分钟

在APP内生成与具体页面无关的悬浮窗,可添加一些快捷操作
首先定义悬浮窗视图,添加点击事件

import Foundation

class MyFloatRoundEntryView:UIView{
    var clickedBack: (() -> ())?
    
    deinit {
        clickedBack = nil
    }
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        let tap = UITapGestureRecognizer(target: self, action: #selector(didTap(gesture:)))
        self.addGestureRecognizer(tap)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError()
    }
    
    @objc func didTap(gesture: UITapGestureRecognizer){
        clickedBack?()
    }
}

添加悬浮窗控制逻辑,默认显示在右下角

import Foundation
import UIKit

class MyFloatWindow {
    static let shared = MyFloatWindow()
    weak var naviController:UINavigationController?
    let screenSize = UIScreen.main.bounds.size
    var roundEntryViewWidth:CGFloat = 80
    var roundEntryViewMargin:CGFloat = 20
    let delegate = UIApplication.shared.delegate as! AppDelegate
    var myFloatRoundEntryView:MyFloatRoundEntryView!
    
    init(){
        roundEntryViewWidth = screenSize.width / CGFloat(14)
        roundEntryViewMargin = screenSize.width / CGFloat(20)
        myFloatRoundEntryView = MyFloatRoundEntryView(frame: CGRect(x: screenSize.width - roundEntryViewMargin - roundEntryViewWidth, y: (screenSize.height - 80), width: roundEntryViewWidth, height: roundEntryViewWidth))
        myFloatRoundEntryView.layer.cornerRadius = roundEntryViewWidth/2
        myFloatRoundEntryView.isHidden = true
        myFloatRoundEntryView.layer.contents = UIImage(named: "back home")?.cgImage
        myFloatRoundEntryView.clickedBack = {[weak self] in
            self!.hideFloatWindow()
            if UIViewController.current()?.isKind(of: BaseWebViewController.self) ?? false {
                UIViewController.current()?.navigationController?.popViewController(animated: false)
            }
            UIViewController.current()?.navigationController?.popToViewController((UIViewController.current()?.navigationController?.viewControllers[1])!, animated: true)
        }
        let pan = UIPanGestureRecognizer(target: self, action: #selector(processRoundEntryView(gesture:)))
        myFloatRoundEntryView.addGestureRecognizer(pan)
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    //显示悬浮窗
    func showFloatWindow(){
        //如果悬浮窗处于隐藏状态,则显示
        if myFloatRoundEntryView.isHidden {
            UIView.animate(withDuration: 0.1, delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
                self.delegate.window?.addSubview(self.myFloatRoundEntryView)
                self.myFloatRoundEntryView.alpha = 1
                self.myFloatRoundEntryView.transform = CGAffineTransform.identity
                    .scaledBy(x: 2, y: 2)
            }) { (finished) in
                self.myFloatRoundEntryView.isHidden = false
            }
        }
    }
    
    //隐藏悬浮窗
    func hideFloatWindow() {
        if !myFloatRoundEntryView.isHidden {
            UIView.animate(withDuration: 0.1, delay: 0, options: UIViewAnimationOptions.curveEaseInOut, animations: {
                self.myFloatRoundEntryView.transform = CGAffineTransform.identity
                .scaledBy(x: 0.5, y: 0.5)
                 self.myFloatRoundEntryView.alpha = 0
            }) { (finished) in
                self.myFloatRoundEntryView.isHidden = true
                self.myFloatRoundEntryView.removeFromSuperview()
            }
        }
    }
    
    @objc
    func processRoundEntryView(gesture: UIPanGestureRecognizer) {
        let point = gesture.location(in: myFloatRoundEntryView.self.superview)
        if gesture.state == .began {
            UIView.animate(withDuration: 0.1, delay: 0, options: .curveEaseOut, animations: {
                self.myFloatRoundEntryView.center = point
            }) { (finished) in
                
            }
        }else if gesture.state == .changed {
            UIView.animate(withDuration: 0.1, delay: 0, options: .curveEaseOut, animations: {
               self.myFloatRoundEntryView.center = point
            }) { (finished) in

            }
        }else if gesture.state == .ended || gesture.state == .cancelled {
            var frame = myFloatRoundEntryView.frame
            //设置横向坐标
            if point.x > screenSize.width/2 {
                frame.origin.x = screenSize.width - roundEntryViewMargin - roundEntryViewWidth
            }else {
                frame.origin.x = roundEntryViewMargin
            }
            //设置最高点
            if point.y < 80 {
                frame.origin.y = 80
            }
            //设置最低点
            if point.y > screenSize.height - 80 {
                frame.origin.y = screenSize.height - 80
            }
            UIView.animate(withDuration: 0.2, delay: 0, options: .curveEaseOut, animations: {
                self.myFloatRoundEntryView.frame = frame
            }) { (finished) in
                
            }
        }
    }
    
}