前言
最近碰到个需求,需要仿微信语音通话缩小化后,保持界面最上层有一个悬浮的小View可以一点击就把刚刚缩放掉的界面再放回来,其实本质就是创造了一个新的Window,在这个window上创建了一个rootController并展示他,缩小化时是把controller dismiss掉了,再次点击那个小View之后把这个controller再展示出来便可以了。同理微信小程序其实也是在一个新的Window中做了一套新的逻辑。随着现在手机性能的提升,多Window同时存在并不会造成严重卡顿,而衍生出来的一种新的开发方式。
实例代码
上代码,这个是根据网上找到的类似效果进行了部分修改的,作者叫冯琦帆
SuspendTool
import Foundation import UIKit enum 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 UIKit let radious: CGFloat = 82 class 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 Foundation import UIKit extension 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微信语音通话最小化内容请搜索自学编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持自学编程网!
- 本文固定链接: https://zxbcw.cn/post/206851/
- 转载请注明:必须在正文中标注并保留原文链接
- QQ群: PHP高手阵营官方总群(344148542)
- QQ群: Yii2.0开发(304864863)