Advertisement
Guest User

Untitled

a guest
Sep 1st, 2016
57
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.83 KB | None | 0 0
  1. import UIKit
  2.  
  3. enum SeparatorType {
  4. case Horisontal
  5. case Vertical
  6. }
  7.  
  8. let kTotalSize: CGFloat = 44; // the total height of the separator (including parts that are not visible
  9. let kVisibleSize: CGFloat = 10; // the height of the visible portion of the separator
  10. let kMargin: CGFloat = (kTotalSize - kVisibleSize) / 2.0; // the height of the non-visible portions of the separator (i.e. above and below the visible portion)
  11. let kMinSize: CGFloat = 10; // the minimum height allowed for views above and below the separator
  12.  
  13. protocol OnConstraintsUpdateProtocol {
  14. func updateConstraintOnBasisOfTouch(touch: UITouch)
  15. }
  16.  
  17. class SeparatorView: UIView {
  18.  
  19. var startConstraint: NSLayoutConstraint? // the constraint that dictates the vertical position of the separator
  20. var primaryView: UIView // the view above the separator
  21. var secondaryView: UIView // the view below the separator
  22.  
  23. // some properties used for handling the touches
  24.  
  25. var oldPosition: CGFloat = 0.0 // the position of the separator before the gesture started
  26. var firstTouch: CGPoint? // the position where the drag gesture started
  27.  
  28. var updateListener: OnConstraintsUpdateProtocol?
  29.  
  30. internal static func addSeparatorBetweenViews(separatorType: SeparatorType, primaryView: UIView, secondaryView: UIView, parentView: UIView) -> SeparatorView {
  31.  
  32. var separator: SeparatorView
  33.  
  34. if (separatorType == .Horisontal) {
  35. separator = HorizontalSeparatorView(primaryView: primaryView, secondaryView: secondaryView)
  36. } else {
  37. separator = VerticalSeparatorView(primaryView: primaryView, secondaryView: secondaryView)
  38. }
  39. separator.setupParentViewConstraints(parentView)
  40. parentView.addSubview(separator)
  41. separator.setupSeparatorConstraints()
  42.  
  43. return separator
  44. }
  45.  
  46. init(primaryView: UIView, secondaryView: UIView){
  47. self.primaryView = primaryView
  48. self.secondaryView = secondaryView
  49. super.init(frame: CGRectZero)
  50. self.translatesAutoresizingMaskIntoConstraints = false
  51. self.userInteractionEnabled = true
  52. self.backgroundColor = UIColor.clearColor()
  53. }
  54.  
  55. func setupParentViewConstraints(parentView: UIView){}
  56.  
  57. func setupSeparatorConstraints(){}
  58.  
  59. required init?(coder aDecoder: NSCoder) {
  60. fatalError("init(coder:) has not been implemented")
  61. }
  62.  
  63. override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
  64. self.firstTouch = touches.first?.locationInView(self.superview)
  65. self.startConstraint!.constant = self.oldPosition;
  66. self.startConstraint!.active = true;
  67. }
  68.  
  69. override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
  70.  
  71. guard let touch = touches.first, event = event else { return }
  72.  
  73. // for more responsive UX, use predicted touches, if possible
  74. let predictedTouch = event.predictedTouchesForTouch(touch)?.last
  75. if ((predictedTouch) != nil) {
  76. updateListener?.updateConstraintOnBasisOfTouch(predictedTouch!)
  77. return;
  78. }
  79. // if no predicted touch found, just use the touch provided
  80. updateListener?.updateConstraintOnBasisOfTouch(touch)
  81. }
  82.  
  83. override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
  84. guard let touch = touches.first else { return }
  85. updateListener?.updateConstraintOnBasisOfTouch(touch)
  86. }
  87.  
  88. override func drawRect(rect: CGRect) {
  89. let path = UIBezierPath(rect: rect)
  90. UIColor.blackColor().set()
  91. path.stroke()
  92. path.fill()
  93. }
  94. }
  95.  
  96. class HorizontalSeparatorView: SeparatorView, OnConstraintsUpdateProtocol {
  97.  
  98. override init(primaryView: UIView, secondaryView: UIView) {
  99. super.init(primaryView: primaryView, secondaryView: secondaryView)
  100. updateListener = self
  101. }
  102.  
  103. required init?(coder aDecoder: NSCoder) {
  104. fatalError("init(coder:) has not been implemented")
  105. }
  106.  
  107. override func setupParentViewConstraints(parentView: UIView) {
  108. parentView.leadingAnchor.constraintEqualToAnchor(primaryView.leadingAnchor).active = true
  109. parentView.trailingAnchor.constraintEqualToAnchor(primaryView.trailingAnchor).active = true
  110. parentView.leadingAnchor.constraintEqualToAnchor(secondaryView.leadingAnchor).active = true
  111. parentView.trailingAnchor.constraintEqualToAnchor(secondaryView.trailingAnchor).active = true
  112. parentView.topAnchor.constraintEqualToAnchor(primaryView.topAnchor).active = true
  113. let height = secondaryView.heightAnchor.constraintEqualToAnchor(primaryView.heightAnchor)
  114. height.priority = 250
  115. height.active = true
  116. parentView.bottomAnchor.constraintEqualToAnchor(secondaryView.bottomAnchor).active = true
  117. }
  118.  
  119. override func setupSeparatorConstraints() {
  120. self.heightAnchor.constraintEqualToConstant(kTotalSize).active = true
  121. self.superview?.leadingAnchor.constraintEqualToAnchor(self.leadingAnchor).active = true
  122. self.superview?.trailingAnchor.constraintEqualToAnchor(self.trailingAnchor).active = true
  123. primaryView.bottomAnchor.constraintEqualToAnchor(self.topAnchor, constant: kMargin).active = true
  124. secondaryView.topAnchor.constraintEqualToAnchor(self.bottomAnchor, constant: -kMargin).active = true
  125.  
  126. startConstraint = self.topAnchor.constraintEqualToAnchor(self.superview?.topAnchor, constant: 0)
  127. }
  128.  
  129. override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
  130. self.oldPosition = self.frame.origin.y;
  131. super.touchesBegan(touches, withEvent: event)
  132. }
  133.  
  134. override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
  135. super.touchesMoved(touches, withEvent: event)
  136. }
  137.  
  138.  
  139. override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
  140. super.touchesEnded(touches, withEvent: event)
  141. }
  142.  
  143. func updateConstraintOnBasisOfTouch(touch: UITouch) {
  144. // calculate where separator should be moved to
  145. var y: CGFloat = self.oldPosition + touch.locationInView(self.superview).y - self.firstTouch!.y
  146.  
  147. // make sure the views above and below are not too small
  148. y = max(y, self.primaryView.frame.origin.y + kMinSize - kMargin)
  149. y = min(y, self.secondaryView.frame.origin.y + self.secondaryView.frame.size.height - (kMargin + kMinSize))
  150.  
  151. // set constraint
  152. self.startConstraint!.constant = y
  153. }
  154.  
  155. override func drawRect(rect: CGRect) {
  156. let separatorRect = CGRectMake(0, kMargin, self.bounds.size.width, kVisibleSize)
  157. super.drawRect(separatorRect)
  158. }
  159.  
  160. }
  161.  
  162. class VerticalSeparatorView: SeparatorView, OnConstraintsUpdateProtocol {
  163.  
  164. override init(primaryView: UIView, secondaryView: UIView) {
  165. super.init(primaryView: primaryView, secondaryView: secondaryView)
  166. updateListener = self
  167. }
  168.  
  169. required init?(coder aDecoder: NSCoder) {
  170. fatalError("init(coder:) has not been implemented")
  171. }
  172.  
  173. override func setupParentViewConstraints(parentView: UIView) {
  174. parentView.topAnchor.constraintEqualToAnchor(primaryView.topAnchor).active = true
  175. parentView.topAnchor.constraintEqualToAnchor(secondaryView.topAnchor).active = true
  176. parentView.bottomAnchor.constraintEqualToAnchor(primaryView.bottomAnchor).active = true
  177. parentView.leadingAnchor.constraintEqualToAnchor(secondaryView.topAnchor).active = true
  178. parentView.bottomAnchor.constraintEqualToAnchor(secondaryView.bottomAnchor).active = true
  179. parentView.leadingAnchor.constraintEqualToAnchor(primaryView.leadingAnchor).active = true
  180. let width = secondaryView.widthAnchor.constraintEqualToAnchor(primaryView.widthAnchor)
  181. width.priority = 250
  182. width.active = true
  183. parentView.trailingAnchor.constraintEqualToAnchor(secondaryView.trailingAnchor).active = true
  184. }
  185.  
  186. override func setupSeparatorConstraints() {
  187. self.widthAnchor.constraintEqualToConstant(kTotalSize).active = true
  188. self.superview?.topAnchor.constraintEqualToAnchor(self.topAnchor).active = true
  189. self.superview?.bottomAnchor.constraintEqualToAnchor(self.bottomAnchor).active = true
  190. primaryView.trailingAnchor.constraintEqualToAnchor(self.leadingAnchor, constant: kMargin).active = true
  191. secondaryView.leadingAnchor.constraintEqualToAnchor(self.trailingAnchor, constant: -kMargin).active = true
  192.  
  193. startConstraint = self.leadingAnchor.constraintEqualToAnchor(self.superview?.leadingAnchor, constant: 0)
  194. }
  195.  
  196. override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
  197. self.oldPosition = self.frame.origin.x;
  198. super.touchesBegan(touches, withEvent: event)
  199. }
  200.  
  201. override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
  202. super.touchesMoved(touches, withEvent: event)
  203. }
  204.  
  205. override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
  206. super.touchesEnded(touches, withEvent: event)
  207. }
  208.  
  209. func updateConstraintOnBasisOfTouch(touch: UITouch) {
  210. // calculate where separator should be moved to
  211. var x: CGFloat = self.oldPosition + touch.locationInView(self.superview).x - self.firstTouch!.x
  212.  
  213. // make sure the views above and below are not too small
  214. x = max(x, self.primaryView.frame.origin.x + kMinSize - kMargin)
  215. x = min(x, self.secondaryView.frame.origin.x + self.secondaryView.frame.size.width - (kMargin + kMinSize))
  216.  
  217. // set constraint
  218. self.startConstraint!.constant = x
  219. }
  220.  
  221. override func drawRect(rect: CGRect) {
  222. let separatorRect = CGRectMake(kMargin, 0, kVisibleSize, self.bounds.size.height)
  223. super.drawRect(separatorRect)
  224. }
  225.  
  226. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement