Swift仿微信语音通话最小化时后的效果实例代码

时间:2021-05-20

前言

最近碰到个需求,需要仿微信语音通话缩小化后,保持界面最上层有一个悬浮的小View可以一点击就把刚刚缩放掉的界面再放回来,其实本质就是创造了一个新的Window,在这个window上创建了一个rootController并展示他,缩小化时是把controller dismiss掉了,再次点击那个小View之后把这个controller再展示出来便可以了。同理微信小程序其实也是在一个新的Window中做了一套新的逻辑。随着现在手机性能的提升,多Window同时存在并不会造成严重卡顿,而衍生出来的一种新的开发方式。

实例代码

上代码,这个是根据网上找到的类似效果进行了部分修改的,作者叫冯琦帆

SuspendTool

import Foundationimport UIKitenum SuspendType { case none case single case multi}class SuspendTool: NSObject { static let sharedInstance = SuspendTool() private var suspendWindows: [SuspendWindow] = []// var semicircle: Semicircle? var origin: CGPoint = CGPoint.init(x: 10, y: 300) static func showSuspendWindow(rootViewController: UIViewController, coverImageName: String) { let tool = SuspendTool.sharedInstance let window = SuspendWindow.init(rootViewController: rootViewController, coverImageName: coverImageName, frame: CGRect.init(origin: tool.origin, size: CGSize.init(width: radious, height: radious))) window.show() tool.suspendWindows.append(window) } static func replaceSuspendWindow(rootViewController: UIViewController, coverImageName: String) { let tool = SuspendTool.sharedInstance tool.suspendWindows.removeAll() let window = SuspendWindow.init(rootViewController: rootViewController, coverImageName: coverImageName, frame: CGRect.init(origin: tool.origin, size: CGSize.init(width: radious, height: radious))) window.show() tool.suspendWindows.append(window) } static func remove(suspendWindow: SuspendWindow) { UIView.animate(withDuration: 0.25, animations: { suspendWindow.alpha = 0 }) { (complete) in if let index = SuspendTool.sharedInstance.suspendWindows.index(of: suspendWindow) { SuspendTool.sharedInstance.suspendWindows.remove(at: index) } } } static func setLatestOrigin(origin: CGPoint) { SuspendTool.sharedInstance.origin = origin }}

SuspendWindow

import UIKitlet radious: CGFloat = 82class SuspendWindow: UIWindow { fileprivate let coverImageName: String fileprivate let space: CGFloat = 15 var containsRootViewController: UIViewController? init(rootViewController: UIViewController ,coverImageName: String, frame: CGRect) { self.coverImageName = coverImageName super.init(frame: frame) // self.rootViewController = rootViewController self.containsRootViewController = rootViewController } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func show() { self.backgroundColor = UIColor.clear self.windowLevel = UIWindow.Level.alert - 1//UIWindowLevelAlert - 1 self.screen = UIScreen.main self.isHidden = false let bgView = UIView() bgView.isUserInteractionEnabled = true bgView.frame = self.bounds bgView.backgroundColor = UIColor.white bgView.layer.cornerRadius = radious / 2.0 bgView.layer.borderColor = UIColor.lightGray.cgColor bgView.layer.borderWidth = 5 bgView.layer.masksToBounds = true self.addSubview(bgView) bgView.addSubview(iconImageView) bgView.addSubview(timeLabel) let panGesture = UIPanGestureRecognizer.init(target: self, action: #selector(didPan(_:))) self.addGestureRecognizer(panGesture) let tapGesture = UITapGestureRecognizer.init(target: self, action: #selector(didTap(_:))) self.addGestureRecognizer(tapGesture) } @objc fileprivate func didTap(_ tapGesture: UITapGestureRecognizer) { SuspendTool.sharedInstance.origin = self.frame.origin self.containsRootViewController?.spread(from: self.self.frame.origin) SuspendTool.remove(suspendWindow: self) } @objc fileprivate func didPan(_ panGesture: UIPanGestureRecognizer) { let point = panGesture.translation(in: panGesture.view) var originX = self.frame.origin.x + point.x if originX < space { originX = space } else if originX > UIScreen.main.bounds.width - radious - space { originX = UIScreen.main.bounds.width - radious - space } var originY = self.frame.origin.y + point.y if originY < space { originY = space } else if originY > UIScreen.main.bounds.height - radious - space { originY = UIScreen.main.bounds.height - radious - space } self.frame = CGRect.init(x: originX, y: originY, width: self.bounds.width, height: self.bounds.height) if panGesture.state == UIGestureRecognizer.State.cancelled || panGesture.state == UIGestureRecognizer.State.ended || panGesture.state == UIGestureRecognizer.State.failed { self.adjustFrameAfterPan() } panGesture.setTranslation(CGPoint.zero, in: self) } fileprivate func adjustFrameAfterPan() { var originX: CGFloat = space if self.center.x < UIScreen.main.bounds.width / 2 { originX = space } else if self.center.x >= UIScreen.main.bounds.width / 2 { originX = UIScreen.main.bounds.width - radious - space } UIView.animate(withDuration: 0.25, animations: { self.frame = CGRect.init(x: originX, y: self.frame.origin.y, width: self.frame.size.width, height: self.frame.size.height) }) { (complete) in SuspendTool.setLatestOrigin(origin: self.frame.origin) } } lazy var timeLabel: UILabel = { let timeLabel = UILabel() timeLabel.frame = CGRect(x: 0, y: 55.5, width: 42, height: 13) timeLabel.center.x = self.bounds.size.width / 2 timeLabel.textAlignment = .center timeLabel.text = "0:00" timeLabel.textColor = UIColor.text timeLabel.font = UIFont.mediumFont(ofSize: 13) return timeLabel }() lazy var iconImageView: UIImageView = { let iconImageView = UIImageView.init(image: UIImage.init(named: coverImageName)) iconImageView.isUserInteractionEnabled = true iconImageView.frame = CGRect(x: 0, y: 12, width: 38, height: 38) iconImageView.center.x = self.bounds.size.width / 2 return iconImageView }()}

UIViewController+FF

import Foundationimport UIKitextension UIViewController { func suspend(coverImageName: String, type: SuspendType) { if type == .none { self.navigationController?.popViewController(animated: true) return } self.view.layer.masksToBounds = true UIView.animate(withDuration: 0.25, animations: { self.view.layer.cornerRadius = radious / 2.0 self.view.frame = CGRect.init(origin: SuspendTool.sharedInstance.origin, size: CGSize.init(width: radious, height: radious)) self.view.layoutIfNeeded() }) { (complete) in self.navigationController?.popViewController(animated: false) if type == .single { SuspendTool.replaceSuspendWindow(rootViewController: self, coverImageName: coverImageName) } else { SuspendTool.showSuspendWindow(rootViewController: self, coverImageName: coverImageName) } } } func spread(from point: CGPoint) { if let isContain = self.navigationController?.viewControllers.contains(self), isContain { return } self.view.frame = CGRect.init(origin: point, size: CGSize.init(width: radious, height: radious)) //UIViewController.currentViewController() UIViewController.currentViewController().navigationController?.pushViewController(self, animated: false) UIView.animate(withDuration: 0.25, animations: { self.view.layer.cornerRadius = 0 self.view.frame = UIScreen.main.bounds self.view.layoutIfNeeded() }) } static func currentViewController() -> UIViewController { var rootViewController: UIViewController? = nil for window in UIApplication.shared.windows { if (window.rootViewController != nil) { rootViewController = window.rootViewController break } } var viewController = rootViewController while (true) { if viewController?.presentedViewController != nil { viewController = viewController!.presentedViewController } else if viewController!.isKind(of: UINavigationController.self) { viewController = (viewController as! UINavigationController).visibleViewController } else if viewController!.isKind(of: UITabBarController.self) { viewController = (viewController as! UITabBarController).selectedViewController } else { break } } return viewController! }}

总结

到此这篇关于Swift仿微信语音通话最小化时后效果的文章就介绍到这了,更多相关Swift微信语音通话最小化内容请搜索以前的文章或继续浏览下面的相关文章希望大家以后多多支持!

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章