Geen omschrijving

FFToastView.swift 9.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  1. //
  2. // FFToastView.swift
  3. // PaiAi
  4. //
  5. // Created by mac on 16/7/21.
  6. // Copyright © 2016年 FFIB. All rights reserved.
  7. //
  8. import UIKit
  9. class FFToastView: UIView {
  10. //文字
  11. var text: String = "" {
  12. didSet {
  13. label.text = text
  14. label.numberOfLines = 0
  15. label.lineBreakMode = .byWordWrapping
  16. label.textAlignment = .center
  17. label.sizeToFit()
  18. }
  19. }
  20. //字体
  21. var textFont = UIFont.systemFont(ofSize: 14)
  22. var textColor = UIColor.white
  23. //转菊花等待指示
  24. lazy var activityIndicatorView = UIActivityIndicatorView(activityIndicatorStyle: .whiteLarge)
  25. // 与父view的centerX距离
  26. var centerXPadding: CGFloat = 0
  27. // 与父view的centerX比例
  28. var centerXMultiplier: CGFloat = 1
  29. // --
  30. var centerYPadding: CGFloat = 0
  31. var centerYMultiplier: CGFloat = 1
  32. // 中间文字上下左右间距
  33. var labelEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10) {
  34. didSet {
  35. if !UIEdgeInsetsEqualToEdgeInsets(labelEdgeInsets, oldValue) {
  36. self.setNeedsUpdateConstraints()
  37. }
  38. }
  39. }
  40. // 边界圆角
  41. var viewCornerRadius: CGFloat = 5 {
  42. didSet {
  43. self.layer.masksToBounds = true
  44. self.layer.cornerRadius = viewCornerRadius
  45. }
  46. }
  47. fileprivate var showing = false
  48. //文字toast
  49. func showToast(inView superview: UIView, duration: TimeInterval) {
  50. showing = true
  51. self.superview?.isUserInteractionEnabled = true
  52. // if label.superview == self {
  53. label.removeFromSuperview()
  54. // }
  55. self.addToSuperView(superview, duration: duration, haveImage: true)
  56. self.addSubview(label)
  57. activityIndicatorView.removeFromSuperview()
  58. addLabelConstraints()
  59. }
  60. func showImageToast(inView superview: UIView, duration: TimeInterval) {
  61. showing = true
  62. self.superview?.isUserInteractionEnabled = true
  63. label.removeFromSuperview()
  64. imageView.removeFromSuperview()
  65. self.addToSuperView(superview, duration: duration)
  66. // if label.superview != self {
  67. self.addSubview(label)
  68. self.addSubview(imageView)
  69. activityIndicatorView.removeFromSuperview()
  70. addImageViewConstraints()
  71. // }
  72. }
  73. //菊花toast
  74. func showLoadingToast(inView superview: UIView, blockSuperView: Bool) {
  75. showing = true
  76. self.superview?.isUserInteractionEnabled = true
  77. label.removeFromSuperview()
  78. self.addAcitvityIndicatorAndAddConstraints()
  79. activityIndicatorView.startAnimating()
  80. if blockSuperView {
  81. superview.isUserInteractionEnabled = false
  82. }
  83. self.addToSuperView(superview, duration: 0)
  84. }
  85. func hideLoadingToast() {
  86. showing = false
  87. activityIndicatorView.stopAnimating()
  88. activityIndicatorView.removeFromSuperview()
  89. self.dismiss()
  90. }
  91. func addToSuperView(_ superview: UIView, duration: TimeInterval, haveImage: Bool = false) {
  92. self.removeFromSuperview()
  93. superview.addSubview(self)
  94. self.layer.removeAllAnimations()
  95. self.alpha = 1
  96. // constrains to superview
  97. // self.useAutoLayout()
  98. self.constraintCenterX = NSLayoutConstraint(item: self, attribute: .centerX, relatedBy: .equal, toItem: superview, attribute: .centerX, multiplier: centerXMultiplier, constant: centerXPadding)
  99. // self.constraintCenterX!.active()
  100. self.constraintCenterY = NSLayoutConstraint(item: self, attribute: .centerY, relatedBy: .equal, toItem: superview, attribute: .centerY, multiplier: centerYMultiplier, constant: centerYPadding)
  101. // self.constraintCenterY!.active()
  102. if self.bounds.width == 0 {
  103. self.superview?.layoutIfNeeded()
  104. }
  105. self.layoutIfNeeded()
  106. if duration > 0 {
  107. self.perform(#selector(FFToastView.dismiss), with: nil, afterDelay: duration)
  108. }
  109. }
  110. @objc func dismiss() {
  111. showing = false
  112. UIView.animate(withDuration: 0.2, animations: {
  113. self.alpha = 0
  114. }, completion: { (_) in
  115. self.superview?.isUserInteractionEnabled = true
  116. if !self.showing {
  117. self.removeFromSuperview()
  118. }
  119. self.alpha = 1
  120. })
  121. }
  122. @discardableResult
  123. class func showToast(inView superview: UIView, withText text: String) -> FFToastView {
  124. defaultInstance.text = text
  125. defaultInstance.showToast(inView: superview, duration: 2)
  126. return defaultInstance
  127. }
  128. @discardableResult
  129. class func showToastAndTime(inView superview: UIView, withText text: String, withDuration duration: TimeInterval) -> FFToastView {
  130. defaultInstance.text = text
  131. defaultInstance.showToast(inView: superview, duration: duration)
  132. return defaultInstance
  133. }
  134. @discardableResult
  135. class func showImageToast(inView superview: UIView, withText text: String, withImage image: String) -> FFToastView {
  136. defaultInstance.text = text
  137. defaultInstance.imageView.image = UIImage(named: image)
  138. defaultInstance.showImageToast(inView: superview, duration: 2)
  139. return defaultInstance
  140. }
  141. class func hideLoadingToast() {
  142. defaultInstance.hideLoadingToast()
  143. }
  144. @discardableResult
  145. class func showLoadingToast(inView superview: UIView, blockSuperView block: Bool) -> FFToastView {
  146. defaultInstance.showLoadingToast(inView: superview, blockSuperView : block)
  147. return defaultInstance
  148. }
  149. // MARK: - -private--
  150. static fileprivate let defaultInstance = FFToastView(frame: CGRect.zero)
  151. fileprivate let label = UILabel()
  152. fileprivate let imageView = UIImageView()
  153. fileprivate var constraintCenterX: NSLayoutConstraint?
  154. fileprivate var constraintCenterY: NSLayoutConstraint?
  155. fileprivate var innerConstraints: [NSLayoutConstraint] = []
  156. fileprivate func applyDefaultSetting() {
  157. self.backgroundColor = UIColor(white: 0, alpha: 0.8)
  158. label.textColor = self.textColor
  159. label.font = self.textFont
  160. self.viewCornerRadius = 5
  161. }
  162. required init?(coder aDecoder: NSCoder) {
  163. super.init(coder: aDecoder)
  164. self.applyDefaultSetting()
  165. }
  166. override init(frame: CGRect) {
  167. super.init(frame: frame)
  168. self.applyDefaultSetting()
  169. }
  170. override func didMoveToSuperview() {
  171. if superview == nil {
  172. self.constraintCenterX = nil
  173. self.constraintCenterY = nil
  174. }
  175. }
  176. func addImageViewConstraints() {
  177. self.removeConstraints(constraints)
  178. if imageView.superview == self && label.superview == self {
  179. let rect = NSString(string: text).boundingRect(with: CGSize(width: kScreenWidth - 50, height: 10000), options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 15)], context: nil)
  180. let size = NSString(string: text).size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14)])
  181. let width = size.width < kScreenWidth - 50 ? size.width : kScreenWidth - 50
  182. imageView.frame = CGRect(x: 34, y: 18, width: 60, height: 60)
  183. label.frame = CGRect(x: 10, y: 90, width: width, height: rect.height)
  184. innerConstraints.removeAll(keepingCapacity: true)
  185. // NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: width + 20).active = true
  186. // NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 114 + rect.height).active = true
  187. }
  188. }
  189. func addLabelConstraints() {
  190. imageView.removeFromSuperview()
  191. self.removeConstraints(constraints)
  192. let rect = NSString(string: text).boundingRect(with: CGSize(width: kScreenWidth - 50, height: 10000), options: .usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 15)], context: nil)
  193. let size = NSString(string: text).size(withAttributes: [NSAttributedStringKey.font: UIFont.systemFont(ofSize: 14)])
  194. let width = size.width < kScreenWidth - 50 ? size.width : kScreenWidth - 50
  195. label.frame = CGRect(x: 10, y: 10, width: width, height: rect.height)
  196. // NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: width + 20).active()
  197. // NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: rect.height + 20).active()
  198. }
  199. fileprivate func addAcitvityIndicatorAndAddConstraints() {
  200. imageView.removeFromSuperview()
  201. removeConstraints(constraints)
  202. if activityIndicatorView.superview != self {
  203. self.addSubview(activityIndicatorView)
  204. // activityIndicatorView.useAutoLayout()
  205. innerConstraints.removeAll()
  206. // NSLayoutConstraint.constraints(withVisualFormat: "H:|-30-[Indicator]-30-|", options: [], metrics: nil, views: ["Indicator": activityIndicatorView]).autolayoutInstall()
  207. // NSLayoutConstraint.constraints(withVisualFormat: "V:|-30-[Indicator]-30-|", options: [], metrics: nil, views: ["Indicator": activityIndicatorView]).autolayoutInstall()
  208. }
  209. }
  210. }