UIView+Extensions.swift 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. import UIKit
  2. public extension UIView {
  3. func makeBorder(color: UIColor = UIColor.red) {
  4. self.layer.borderColor = color.cgColor
  5. self.layer.borderWidth = 2
  6. }
  7. func alignLeadingToAnchor(_ anchor: NSLayoutXAxisAnchor, paddingLeading: CGFloat = 0.0, priority: UILayoutPriority? = .none) {
  8. let constraint = self.leadingAnchor.constraint(equalTo: anchor, constant: paddingLeading)
  9. if let priority = priority {
  10. constraint.priority = priority
  11. }
  12. constraint.isActive = true
  13. }
  14. func alignTrailingToAnchor(_ anchor: NSLayoutXAxisAnchor, paddingTrailing: CGFloat = 0.0, priority: UILayoutPriority? = .none) {
  15. let constraint = self.trailingAnchor.constraint(equalTo: anchor, constant: -paddingTrailing)
  16. if let priority = priority {
  17. constraint.priority = priority
  18. }
  19. constraint.isActive = true
  20. }
  21. func alignTopToAnchor(_ anchor: NSLayoutYAxisAnchor, paddingTop: CGFloat = 0.0, priority: UILayoutPriority? = .none) {
  22. let constraint = self.topAnchor.constraint(equalTo: anchor, constant: paddingTop)
  23. if let priority = priority {
  24. constraint.priority = priority
  25. }
  26. constraint.isActive = true
  27. }
  28. func alignBottomToAnchor(_ anchor: NSLayoutYAxisAnchor, paddingBottom: CGFloat = 0.0, priority: UILayoutPriority? = .none) {
  29. let constraint = self.bottomAnchor.constraint(equalTo: anchor, constant: -paddingBottom)
  30. if let priority = priority {
  31. constraint.priority = priority
  32. }
  33. constraint.isActive = true
  34. }
  35. func fill(view: UIView, paddingLeading: CGFloat? = 0.0, paddingTrailing: CGFloat? = 0.0, paddingTop: CGFloat? = 0.0, paddingBottom: CGFloat? = 0.0) {
  36. alignLeadingToAnchor(view.leadingAnchor, paddingLeading: paddingLeading ?? 0.0)
  37. alignTrailingToAnchor(view.trailingAnchor, paddingTrailing: paddingTrailing ?? 0.0)
  38. alignTopToAnchor(view.topAnchor, paddingTop: paddingTop ?? 0.0)
  39. alignBottomToAnchor(view.bottomAnchor, paddingBottom: paddingBottom ?? 0.0)
  40. }
  41. func constraintAlignTopTo(_ view: UIView) -> NSLayoutConstraint {
  42. return constraintAlignTopTo(view, paddingTop: 0.0)
  43. }
  44. func constraintAlignTopTo(_ view: UIView, paddingTop: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  45. let constraint = NSLayoutConstraint(
  46. item: self,
  47. attribute: .top,
  48. relatedBy: .equal,
  49. toItem: view,
  50. attribute: .top,
  51. multiplier: 1.0,
  52. constant: paddingTop)
  53. if let priority = priority {
  54. constraint.priority = priority
  55. }
  56. return constraint
  57. }
  58. /**
  59. ensure the top of self is aligned with or lower than another view
  60. can be used in conjunction with constraintAlignCenterY
  61. */
  62. func constraintAlignTopMaxTo(_ view: UIView, paddingTop: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  63. let constraint = NSLayoutConstraint(
  64. item: self,
  65. attribute: .top,
  66. relatedBy: .greaterThanOrEqual,
  67. toItem: view,
  68. attribute: .top,
  69. multiplier: 1.0,
  70. constant: paddingTop)
  71. if let priority = priority {
  72. constraint.priority = priority
  73. }
  74. return constraint
  75. }
  76. func constraintAlignBottomTo(_ view: UIView, paddingBottom: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  77. let constraint = NSLayoutConstraint(
  78. item: self,
  79. attribute: .bottom,
  80. relatedBy: .equal,
  81. toItem: view,
  82. attribute: .bottom,
  83. multiplier: 1.0,
  84. constant: -paddingBottom)
  85. if let priority = priority {
  86. constraint.priority = priority
  87. }
  88. return constraint
  89. }
  90. func constraintAlignLeadingTo(_ view: UIView, paddingLeading: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  91. let constraint = NSLayoutConstraint(
  92. item: self,
  93. attribute: .leading,
  94. relatedBy: .equal,
  95. toItem: view,
  96. attribute: .leading,
  97. multiplier: 1.0,
  98. constant: paddingLeading)
  99. if let priority = priority {
  100. constraint.priority = priority
  101. }
  102. return constraint
  103. }
  104. /**
  105. allows to align leading to the leading of another view but allows left side shrinking
  106. */
  107. func constraintAlignLeadingMaxTo(_ view: UIView, paddingLeading: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  108. let constraint = NSLayoutConstraint(
  109. item: self,
  110. attribute: .leading,
  111. relatedBy: .greaterThanOrEqual,
  112. toItem: view,
  113. attribute: .leading,
  114. multiplier: 1.0,
  115. constant: paddingLeading)
  116. if let priority = priority {
  117. constraint.priority = priority
  118. }
  119. return constraint
  120. }
  121. func constraintAlignTrailingTo(_ view: UIView, paddingTrailing: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  122. let constraint = NSLayoutConstraint(
  123. item: self,
  124. attribute: .trailing,
  125. relatedBy: .equal,
  126. toItem: view,
  127. attribute: .trailing,
  128. multiplier: 1.0,
  129. constant: -paddingTrailing)
  130. if let priority = priority {
  131. constraint.priority = priority
  132. }
  133. return constraint
  134. }
  135. /**
  136. allows to align trailing to the trailing of another view but allows right side shrinking
  137. */
  138. func constraintAlignTrailingMaxTo(_ view: UIView, paddingTrailing: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  139. let constraint = NSLayoutConstraint(
  140. item: self,
  141. attribute: .trailing,
  142. relatedBy: .lessThanOrEqual,
  143. toItem: view,
  144. attribute: .trailing,
  145. multiplier: 1.0,
  146. constant: -paddingTrailing)
  147. if let priority = priority {
  148. constraint.priority = priority
  149. }
  150. return constraint
  151. }
  152. func constraintToBottomOf(_ view: UIView, paddingTop: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  153. let constraint = NSLayoutConstraint(
  154. item: self,
  155. attribute: .top,
  156. relatedBy: .equal,
  157. toItem: view,
  158. attribute: .bottom,
  159. multiplier: 1.0,
  160. constant: paddingTop)
  161. if let priority = priority {
  162. constraint.priority = priority
  163. }
  164. return constraint
  165. }
  166. func constraintToTrailingOf(_ view: UIView, paddingLeading: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  167. let constraint = NSLayoutConstraint(
  168. item: self,
  169. attribute: .leading,
  170. relatedBy: .equal,
  171. toItem: view,
  172. attribute: .trailing,
  173. multiplier: 1.0,
  174. constant: paddingLeading)
  175. if let priority = priority {
  176. constraint.priority = priority
  177. }
  178. return constraint
  179. }
  180. func constraintTrailingToLeadingOf(_ view: UIView, paddingTrailing: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  181. let constraint = NSLayoutConstraint(
  182. item: self,
  183. attribute: .trailing,
  184. relatedBy: .equal,
  185. toItem: view,
  186. attribute: .leading,
  187. multiplier: 1.0,
  188. constant: -paddingTrailing)
  189. if let priority = priority {
  190. constraint.priority = priority
  191. }
  192. return constraint
  193. }
  194. func constraintCenterXTo(_ view: UIView, paddingX: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  195. let constraint = NSLayoutConstraint(item: self,
  196. attribute: .centerX,
  197. relatedBy: .equal,
  198. toItem: view,
  199. attribute: .centerX,
  200. multiplier: 1.0,
  201. constant: paddingX)
  202. if let priority = priority {
  203. constraint.priority = priority
  204. }
  205. return constraint
  206. }
  207. func constraintCenterYTo(_ view: UIView, paddingY: CGFloat = 0.0, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  208. let constraint = NSLayoutConstraint(item: self,
  209. attribute: .centerY,
  210. relatedBy: .equal,
  211. toItem: view,
  212. attribute: .centerY,
  213. multiplier: 1.0,
  214. constant: paddingY)
  215. if let priority = priority {
  216. constraint.priority = priority
  217. }
  218. return constraint
  219. }
  220. func constraintHeightTo(_ height: CGFloat, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  221. let constraint = heightAnchor.constraint(equalToConstant: height)
  222. if let priority = priority {
  223. constraint.priority = priority
  224. }
  225. return constraint
  226. }
  227. func constraintWidthTo(_ width: CGFloat, priority: UILayoutPriority? = .none) -> NSLayoutConstraint {
  228. let constraint = widthAnchor.constraint(equalToConstant: width)
  229. if let priority = priority {
  230. constraint.priority = priority
  231. }
  232. return constraint
  233. }
  234. func fillSuperview() {
  235. guard let superview = self.superview else {
  236. return
  237. }
  238. translatesAutoresizingMaskIntoConstraints = false
  239. let constraints: [NSLayoutConstraint] = [
  240. leftAnchor.constraint(equalTo: superview.leftAnchor),
  241. rightAnchor.constraint(equalTo: superview.rightAnchor),
  242. topAnchor.constraint(equalTo: superview.topAnchor),
  243. bottomAnchor.constraint(equalTo: superview.bottomAnchor)]
  244. NSLayoutConstraint.activate(constraints)
  245. }
  246. func centerInSuperview() {
  247. guard let superview = self.superview else {
  248. return
  249. }
  250. translatesAutoresizingMaskIntoConstraints = false
  251. let constraints: [NSLayoutConstraint] = [
  252. centerXAnchor.constraint(equalTo: superview.centerXAnchor),
  253. centerYAnchor.constraint(equalTo: superview.centerYAnchor)
  254. ]
  255. NSLayoutConstraint.activate(constraints)
  256. }
  257. func constraint(equalTo size: CGSize) {
  258. guard superview != nil else { return }
  259. translatesAutoresizingMaskIntoConstraints = false
  260. let constraints: [NSLayoutConstraint] = [
  261. widthAnchor.constraint(equalToConstant: size.width),
  262. heightAnchor.constraint(equalToConstant: size.height)
  263. ]
  264. NSLayoutConstraint.activate(constraints)
  265. }
  266. @discardableResult
  267. func addConstraints(_ top: NSLayoutYAxisAnchor? = nil, left: NSLayoutXAxisAnchor? = nil, bottom: NSLayoutYAxisAnchor? = nil, right: NSLayoutXAxisAnchor? = nil, centerY: NSLayoutYAxisAnchor? = nil, centerX: NSLayoutXAxisAnchor? = nil, topConstant: CGFloat = 0, leftConstant: CGFloat = 0, bottomConstant: CGFloat = 0, rightConstant: CGFloat = 0, centerYConstant: CGFloat = 0, centerXConstant: CGFloat = 0, widthConstant: CGFloat = 0, heightConstant: CGFloat = 0) -> [NSLayoutConstraint] {
  268. if self.superview == nil {
  269. return []
  270. }
  271. translatesAutoresizingMaskIntoConstraints = false
  272. var constraints = [NSLayoutConstraint]()
  273. if let top = top {
  274. let constraint = topAnchor.constraint(equalTo: top, constant: topConstant)
  275. constraint.identifier = "top"
  276. constraints.append(constraint)
  277. }
  278. if let left = left {
  279. let constraint = leftAnchor.constraint(equalTo: left, constant: leftConstant)
  280. constraint.identifier = "left"
  281. constraints.append(constraint)
  282. }
  283. if let bottom = bottom {
  284. let constraint = bottomAnchor.constraint(equalTo: bottom, constant: -bottomConstant)
  285. constraint.identifier = "bottom"
  286. constraints.append(constraint)
  287. }
  288. if let right = right {
  289. let constraint = rightAnchor.constraint(equalTo: right, constant: -rightConstant)
  290. constraint.identifier = "right"
  291. constraints.append(constraint)
  292. }
  293. if let centerY = centerY {
  294. let constraint = centerYAnchor.constraint(equalTo: centerY, constant: centerYConstant)
  295. constraint.identifier = "centerY"
  296. constraints.append(constraint)
  297. }
  298. if let centerX = centerX {
  299. let constraint = centerXAnchor.constraint(equalTo: centerX, constant: centerXConstant)
  300. constraint.identifier = "centerX"
  301. constraints.append(constraint)
  302. }
  303. if widthConstant > 0 {
  304. let constraint = widthAnchor.constraint(equalToConstant: widthConstant)
  305. constraint.identifier = "width"
  306. constraints.append(constraint)
  307. }
  308. if heightConstant > 0 {
  309. let constraint = heightAnchor.constraint(equalToConstant: heightConstant)
  310. constraint.identifier = "height"
  311. constraints.append(constraint)
  312. }
  313. NSLayoutConstraint.activate(constraints)
  314. return constraints
  315. }
  316. }