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

 更新时间:2021年03月04日 11:45:39   作者:醉梦弦音  
这篇文章主要介绍了Swift仿微信语音通话最小化时后的效果的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言

最近碰到个需求,需要仿微信语音通话缩小化后,保持界面最上层有一个悬浮的小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微信语音通话最小化内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Swift自定义iOS中的TabBarController并为其添加动画

    Swift自定义iOS中的TabBarController并为其添加动画

    这篇文章主要介绍了Swift自定义iOS中的TabBarController并为其添加动画的方法,即自定义TabBarController中的的TabBar并为自定义的TabBar增加动画效果,需要的朋友可以参考下
    2016-04-04
  • 浅析Swift中struct与class的区别(汇编角度底层分析)

    浅析Swift中struct与class的区别(汇编角度底层分析)

    这篇文章主要介绍了Swift中struct与class的区别 ,本文从汇编角度分析struct与class的区别,通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • Swift中如何避免循环引用的方法

    Swift中如何避免循环引用的方法

    本篇文章主要介绍了Swift中如何避免循环引用的方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2017-12-12
  • swift使用SDPhotoBriwser浏览图片教程

    swift使用SDPhotoBriwser浏览图片教程

    这篇文章主要为大家介绍了swift如何使用SDPhotoBriwser浏览图片的教程示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-10-10
  • Swift 中的 RegexBuilder学习指南

    Swift 中的 RegexBuilder学习指南

    这篇文章主要为大家介绍了Swift中的RegexBuilder学习指南,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-04-04
  • RxSwift使用技巧之过滤操作详解

    RxSwift使用技巧之过滤操作详解

    RxSwift的目的是让让数据/事件流和异步任务能够更方便的序列化处理,能够使用Swift进行响应式编程,下面这篇文章主要给大家介绍了关于RxSwift使用技巧之过滤操作的相关资料,需要的朋友可以参考下。
    2017-09-09
  • 简单分析Swift语言的一些基本特征

    简单分析Swift语言的一些基本特征

    这篇文章主要介绍了Swift语言的一些基本特征,本文从各语言最基础的类与对象等方面来讲,需要的朋友可以参考下
    2015-07-07
  • Swift开发之UITableView状态切换效果

    Swift开发之UITableView状态切换效果

    这篇文章主要介绍了Swift开发之UITableView状态切换效果的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-08-08
  • Combine中错误处理和Scheduler使用详解

    Combine中错误处理和Scheduler使用详解

    这篇文章主要为大家介绍了Combine中错误处理和Scheduler使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-12-12
  • Swift Json实例详细解析

    Swift Json实例详细解析

    这篇文章主要给大家介绍了关于Swift Json解析的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考借鉴,下面随着小编来一起学习学习吧。
    2018-03-03

最新评论