You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

360 lines
9.4 KiB

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
  1. //
  2. // UIViewExtension.swift
  3. // GMERemittance
  4. //
  5. // Created by Fm-user on 12/23/17.
  6. // Copyright © 2017 Gobal Money Express Co. Ltd. All rights reserved.
  7. //
  8. import Foundation
  9. import UIKit
  10. import VisualEffectView
  11. extension UIView {
  12. func rounded() {
  13. self.layer.cornerRadius = self.frame.height / 2
  14. }
  15. func addBlur() {
  16. let visualEffectView = VisualEffectView(frame: self.frame)
  17. visualEffectView.colorTint = .clear
  18. visualEffectView.colorTintAlpha = 0.2
  19. visualEffectView.blurRadius = 3
  20. visualEffectView.scale = 1
  21. visualEffectView.isUserInteractionEnabled = false
  22. self.addSubview(visualEffectView)
  23. }
  24. }
  25. extension UIView {
  26. func fadeIn(
  27. duration: TimeInterval = 1.0,
  28. delay: TimeInterval = 0.0,
  29. completion: @escaping ((Bool) -> Void) = {(finished: Bool) -> Void in}) {
  30. UIView.animate(
  31. withDuration: duration,
  32. delay: delay,
  33. options: UIView.AnimationOptions.curveEaseIn,
  34. animations: {
  35. self.alpha = 1.0
  36. },
  37. completion: completion
  38. )
  39. }
  40. func fadeOut(
  41. duration: TimeInterval = 1.0,
  42. delay: TimeInterval = 3.0,
  43. completion: @escaping (Bool) -> Void = {(finished: Bool) -> Void in}
  44. ) {
  45. UIView.animate(
  46. withDuration: duration,
  47. delay: delay,
  48. options: UIView.AnimationOptions.curveEaseIn,
  49. animations: {
  50. self.alpha = 0.0
  51. },
  52. completion: completion
  53. )
  54. }
  55. }
  56. // MARK: - Animator
  57. extension UIView {
  58. func bottomToOrigin(duration: Double = 0.2) {
  59. let transform = CGAffineTransform(translationX: 0, y: self.bounds.height * 2)
  60. self.transform = transform
  61. let animator = UIViewPropertyAnimator(
  62. duration: duration,
  63. curve: .linear
  64. ) {
  65. let transform = CGAffineTransform(translationX: 0, y: 0)
  66. self.transform = transform
  67. }
  68. animator.startAnimation()
  69. }
  70. func originToBottom(duration: Double = 0.1, completion: @escaping () -> Void ) {
  71. let transform = CGAffineTransform(translationX: 0, y: 0)
  72. self.transform = transform
  73. let animator = UIViewPropertyAnimator(
  74. duration: duration,
  75. curve: .linear) {
  76. let transform = CGAffineTransform(translationX: 0, y: self.bounds.height * 2)
  77. self.transform = transform
  78. }
  79. animator.addCompletion { _ in
  80. completion()
  81. }
  82. animator.startAnimation()
  83. }
  84. func popUpBouncy(duration: Double = 0.1) {
  85. alpha = 0.0
  86. let transform = CGAffineTransform(scaleX: 0.8, y: 0.8)
  87. self.transform = transform
  88. UIView.animate(
  89. withDuration:duration,
  90. delay: duration,
  91. usingSpringWithDamping: 0.2,
  92. initialSpringVelocity: 10,
  93. animations: {
  94. self.alpha = 1.0
  95. let transform = CGAffineTransform(scaleX: 1, y: 1)
  96. self.transform = transform
  97. }
  98. )
  99. }
  100. func animateHidden(isHidden: Bool, duration: Double = 1.0) {
  101. self.isHidden = isHidden
  102. UIView.animate(withDuration: duration) {
  103. self.alpha = isHidden ? 0 : 1
  104. }
  105. }
  106. func travelSubView(block: (_ view: UIView, _ stop: inout Bool) -> Void) {
  107. var stop = false
  108. block(self, &stop)
  109. if !stop {
  110. self.subviews.forEach { $0.travelSubView(block: block) }
  111. }
  112. }
  113. }
  114. // MARK: - FOR Badge
  115. extension UIView {
  116. /*
  117. * Assign badge with only text.
  118. */
  119. /// - parameter text: The badge value, use nil to remove exsiting badge.
  120. @objc public func badge(text badgeText: String?) {
  121. badge(text: badgeText, appearance: BadgeAppearance())
  122. }
  123. /// - parameter text: The badge value, use nil to remove exsiting badge.
  124. /// - parameter appearance: The appearance of the badge.
  125. public func badge(text badgeText: String?, appearance: BadgeAppearance) {
  126. badge(text: badgeText, badgeEdgeInsets: nil, appearance: appearance)
  127. }
  128. /*
  129. * Assign badge with text and edge insets.
  130. */
  131. @available(*, deprecated, message: "Use badge(text: String?, appearance:BadgeAppearance)")
  132. /// badge
  133. ///
  134. /// - Parameters:
  135. /// - badgeText: badge's Text
  136. /// - badgeEdgeInsets: badge's Inset
  137. @objc public func badge(text badgeText: String?, badgeEdgeInsets: UIEdgeInsets) {
  138. badge(text: badgeText, badgeEdgeInsets: badgeEdgeInsets, appearance: BadgeAppearance())
  139. }
  140. /*
  141. * Assign badge with text,insets, and appearance.
  142. */
  143. public func badge (
  144. text badgeText:String?,
  145. badgeEdgeInsets: UIEdgeInsets?,
  146. appearance: BadgeAppearance
  147. ) {
  148. //Create badge label
  149. var badgeLabel: BadgeLabel!
  150. var doesBadgeExist = false
  151. //Find badge in subviews if exists
  152. for view in subviews {
  153. if view.tag == 1, let label = view as? BadgeLabel {
  154. badgeLabel = label
  155. }
  156. }
  157. //If assigned text is nil (request to remove badge) and badge label is not nil:
  158. if badgeText == nil && badgeLabel != nil {
  159. if appearance.animate {
  160. UIView.animate(
  161. withDuration: appearance.duration,
  162. animations: {
  163. badgeLabel.alpha = 0.0
  164. badgeLabel.transform = CGAffineTransform(scaleX: 0.1, y: 0.1)
  165. },
  166. completion: { _ in
  167. badgeLabel.removeFromSuperview()
  168. }
  169. )
  170. } else {
  171. badgeLabel.removeFromSuperview()
  172. }
  173. return
  174. } else if badgeText == nil && badgeLabel == nil {
  175. return
  176. }
  177. //Badge label is nil (There was no previous badge)
  178. if (badgeLabel == nil) {
  179. //init badge label variable
  180. badgeLabel = BadgeLabel()
  181. //assign tag to badge label
  182. badgeLabel.tag = 1
  183. } else {
  184. doesBadgeExist = true
  185. }
  186. let oldWidth: CGFloat? = doesBadgeExist ? badgeLabel.frame.width : nil
  187. //Set the text on the badge label
  188. badgeLabel.text = badgeText
  189. //Set font size
  190. badgeLabel.font = UIFont.systemFont(ofSize: appearance.textSize)
  191. badgeLabel.sizeToFit()
  192. //set the allignment
  193. badgeLabel.textAlignment = appearance.textAlignment
  194. //set background color
  195. badgeLabel.layer.backgroundColor = appearance.backgroundColor.cgColor
  196. //set text color
  197. badgeLabel.textColor = appearance.textColor
  198. //get current badge size
  199. let badgeSize = badgeLabel.frame.size
  200. //calculate width and height with minimum height and width of 20
  201. let height = max(18, Double(badgeSize.height) + 5.0)
  202. let width = max(height, Double(badgeSize.width) + 10.0)
  203. badgeLabel.frame.size = CGSize(width: width, height: height)
  204. //add to subview
  205. if doesBadgeExist {
  206. //remove view to delete constraints
  207. badgeLabel.removeFromSuperview()
  208. }
  209. addSubview(badgeLabel)
  210. //The distance from the center of the view (vertically)
  211. let centerY =
  212. appearance.distanceFromCenterY == 0 ? -(bounds.size.height / 2) : appearance.distanceFromCenterY
  213. //The distance from the center of the view (horizontally)
  214. let centerX =
  215. appearance.distanceFromCenterX == 0 ? (bounds.size.width / 2) : appearance.distanceFromCenterX
  216. //disable auto resizing mask
  217. badgeLabel.translatesAutoresizingMaskIntoConstraints = false
  218. //add height constraint
  219. addConstraint(
  220. NSLayoutConstraint(
  221. item: badgeLabel!,
  222. attribute: .height,
  223. relatedBy: .equal,
  224. toItem: nil,
  225. attribute: .notAnAttribute,
  226. multiplier: 1.0,
  227. constant: CGFloat(height)
  228. )
  229. )
  230. //add width constraint
  231. addConstraint(
  232. NSLayoutConstraint(
  233. item: badgeLabel!,
  234. attribute: .width,
  235. relatedBy: .equal,
  236. toItem: nil,
  237. attribute: .notAnAttribute,
  238. multiplier: 1.0,
  239. constant: CGFloat(width)
  240. )
  241. )
  242. //add vertical constraint
  243. addConstraint(
  244. NSLayoutConstraint(
  245. item: badgeLabel!,
  246. attribute: .centerX,
  247. relatedBy: .equal,
  248. toItem: self,
  249. attribute: .centerX,
  250. multiplier: 1.0,
  251. constant: centerX
  252. )
  253. )
  254. //add horizontal constraint
  255. addConstraint(
  256. NSLayoutConstraint(
  257. item: badgeLabel!,
  258. attribute: .centerY,
  259. relatedBy: .equal,
  260. toItem: self,
  261. attribute: .centerY,
  262. multiplier: 1.0,
  263. constant: centerY
  264. )
  265. )
  266. badgeLabel.layer.borderColor = appearance.borderColor.cgColor
  267. badgeLabel.layer.borderWidth = appearance.borderWidth
  268. //corner radius
  269. badgeLabel.layer.cornerRadius = badgeLabel.frame.size.height / 2
  270. //setup shadow
  271. if appearance.allowShadow {
  272. badgeLabel.layer.shadowOffset = CGSize(width: 1, height: 1)
  273. badgeLabel.layer.shadowRadius = 1
  274. badgeLabel.layer.shadowOpacity = 0.5
  275. badgeLabel.layer.shadowColor = UIColor.black.cgColor
  276. }
  277. //badge does not exist, meaning we are adding a new one
  278. if !doesBadgeExist {
  279. //should it animate?
  280. if appearance.animate {
  281. badgeLabel.transform = CGAffineTransform(scaleX: 0, y: 0)
  282. UIView.animate(
  283. withDuration: appearance.duration,
  284. delay: 0,
  285. usingSpringWithDamping: 0.5,
  286. initialSpringVelocity: 0.5,
  287. options: [],
  288. animations: {
  289. badgeLabel.transform = .identity
  290. },
  291. completion: nil
  292. )
  293. }
  294. } else {
  295. if appearance.animate, let oldWidth = oldWidth {
  296. let currentWidth = badgeLabel.frame.width
  297. badgeLabel.frame.size.width = oldWidth
  298. UIView.animate(withDuration: appearance.duration) {
  299. badgeLabel.frame.size.width = currentWidth
  300. }
  301. }
  302. }
  303. }
  304. }