Preface
Recently I encountered a need to reduce the number of voice calls imitating WeChat, and keep a floating small view on the top of the interface. You can put the interface that has just been scaled back with just one click. In fact, the essence is to create a new Window, create a rootController on this window and display it. When reducing, the controller is dismissed. Click the small View again and then display the controller again. Similarly, WeChat applets actually have made a new set of logic in a new Window. With the improvement of mobile phone performance now, the existence of multiple Window will not cause serious lag, and a new development method has been derived.
Example code
The code above, this was partially modified based on similar effects found on the Internet. The author is Feng Qifan
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 = (x: 10, y: 300) static func showSuspendWindow(rootViewController: UIViewController, coverImageName: String) { let tool = let window = (rootViewController: rootViewController, coverImageName: coverImageName, frame: (origin: , size: (width: radious, height: radious))) () (window) } static func replaceSuspendWindow(rootViewController: UIViewController, coverImageName: String) { let tool = () let window = (rootViewController: rootViewController, coverImageName: coverImageName, frame: (origin: , size: (width: radious, height: radious))) () (window) } static func remove(suspendWindow: SuspendWindow) { (withDuration: 0.25, animations: { = 0 }) { (complete) in if let index = (of: suspendWindow) { (at: index) } } } static func setLatestOrigin(origin: CGPoint) { = 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) { = coverImageName (frame: frame) // = rootViewController = rootViewController } required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } func show() { = = - 1//UIWindowLevelAlert - 1 = = false let bgView = UIView() = true = = = radious / 2.0 = = 5 = true (bgView) (iconImageView) (timeLabel) let panGesture = (target: self, action: #selector(didPan(_:))) (panGesture) let tapGesture = (target: self, action: #selector(didTap(_:))) (tapGesture) } @objc fileprivate func didTap(_ tapGesture: UITapGestureRecognizer) { = ?.spread(from: ) (suspendWindow: self) } @objc fileprivate func didPan(_ panGesture: UIPanGestureRecognizer) { let point = (in: ) var originX = + if originX < space { originX = space } else if originX > - radious - space { originX = - radious - space } var originY = + if originY < space { originY = space } else if originY > - radious - space { originY = - radious - space } = (x: originX, y: originY, width: , height: ) if == || == || == { () } (, in: self) } fileprivate func adjustFrameAfterPan() { var originX: CGFloat = space if < / 2 { originX = space } else if >= / 2 { originX = - radious - space } (withDuration: 0.25, animations: { = (x: originX, y: , width: , height: ) }) { (complete) in (origin: ) } } lazy var timeLabel: UILabel = { let timeLabel = UILabel() = CGRect(x: 0, y: 55.5, width: 42, height: 13) = / 2 = .center = "0:00" = = (ofSize: 13) return timeLabel }() lazy var iconImageView: UIImageView = { let iconImageView = (image: (named: coverImageName)) = true = CGRect(x: 0, y: 12, width: 38, height: 38) = / 2 return iconImageView }() }
UIViewController+FF
import Foundation import UIKit extension UIViewController { func suspend(coverImageName: String, type: SuspendType) { if type == .none { ?.popViewController(animated: true) return } = true (withDuration: 0.25, animations: { = radious / 2.0 = (origin: , size: (width: radious, height: radious)) () }) { (complete) in ?.popViewController(animated: false) if type == .single { (rootViewController: self, coverImageName: coverImageName) } else { (rootViewController: self, coverImageName: coverImageName) } } } func spread(from point: CGPoint) { if let isContain = ?.(self), isContain { return } = (origin: point, size: (width: radious, height: radious)) //() ().navigationController?.pushViewController(self, animated: false) (withDuration: 0.25, animations: { = 0 = () }) } static func currentViewController() -> UIViewController { var rootViewController: UIViewController? = nil for window in { if ( != nil) { rootViewController = break } } var viewController = rootViewController while (true) { if viewController?.presentedViewController != nil { viewController = viewController!.presentedViewController } else if viewController!.isKind(of: ) { viewController = (viewController as! UINavigationController).visibleViewController } else if viewController!.isKind(of: ) { viewController = (viewController as! UITabBarController).selectedViewController } else { break } } return viewController! } }
Summarize
This is the article about the effect of minimizing Swift’s imitation WeChat voice call. For more related content on minimizing Swift WeChat voice call, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!