SoFunction
Updated on 2025-04-09

Swift imitation of the effect example code after minimizing WeChat voice calls

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!