Guest User

Untitled

a guest
Jul 12th, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 3.13 KB | None | 0 0
  1. import Foundation
  2.  
  3. final class ConcealingTitleView: UIView {
  4. private let label = UILabel()
  5. private var contentOffset: CGFloat = 0 {
  6. didSet {
  7. label.frame.origin.y = titleVerticalPositionAdjusted(by: contentOffset)
  8. }
  9. }
  10. var text: String = "" {
  11. didSet {
  12. label.text = text
  13. label.textColor = UIColor.white
  14. label.font = UIFont.systemFont(ofSize: 17.0, weight: .semibold)
  15. setNeedsLayout()
  16. }
  17. }
  18.  
  19. // MARK: Initializers
  20.  
  21. override init(frame: CGRect) {
  22. super.init(frame: frame)
  23.  
  24. addSubview(label)
  25. clipsToBounds = true
  26. isUserInteractionEnabled = false
  27. }
  28.  
  29. required init?(coder aDecoder: NSCoder) {
  30. fatalError("init(coder:) has not been implemented")
  31. }
  32.  
  33. // MARK: View lifecycle
  34.  
  35. override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
  36. super.traitCollectionDidChange(previousTraitCollection)
  37. sizeToFit()
  38. }
  39.  
  40. override func sizeThatFits(_ size: CGSize) -> CGSize {
  41. if #available(iOS 11.0, *) {
  42. return super.sizeThatFits(size)
  43. } else {
  44. let height = (typedSuperview() as? UINavigationBar)?.bounds.height ?? 0.0
  45. let labelSize = label.sizeThatFits(CGSize(width: size.width, height: height))
  46. return CGSize(width: min(labelSize.width, size.width), height: height)
  47. }
  48. }
  49.  
  50. private func layoutSubviews_10() {
  51. guard let navBar = typedSuperview() as? UINavigationBar else { return }
  52. let center = convert(navBar.center, from: navBar)
  53. let size = label.sizeThatFits(bounds.size)
  54. let x = max(bounds.minX, center.x - size.width * 0.5)
  55. let y: CGFloat
  56.  
  57. if contentOffset == 0 {
  58. y = bounds.maxY
  59. } else {
  60. y = titleVerticalPositionAdjusted(by: contentOffset)
  61. }
  62.  
  63. label.frame = CGRect(x: x, y: y, width: min(size.width, bounds.width), height: size.height)
  64. }
  65.  
  66. private func layoutSubviews_11() {
  67. let size = label.sizeThatFits(bounds.size)
  68. let x: CGFloat
  69. let y: CGFloat
  70.  
  71. x = bounds.midX - size.width * 0.5
  72.  
  73. if contentOffset == 0 {
  74. y = bounds.maxY
  75. } else {
  76. y = titleVerticalPositionAdjusted(by: contentOffset)
  77. }
  78.  
  79. label.frame = CGRect(x: x, y: y, width: size.width, height: size.height)
  80. }
  81.  
  82. override func layoutSubviews() {
  83. super.layoutSubviews()
  84.  
  85. if #available(iOS 11.0, *) {
  86. layoutSubviews_11()
  87. } else {
  88. layoutSubviews_10()
  89. }
  90. }
  91.  
  92. // MARK:
  93.  
  94. /// Using the UIScrollViewDelegate it moves the inner UILabel to move up and down following the scroll offset.
  95. ///
  96. /// - Parameters:
  97. /// - scrollView: The scroll-view object in which the scrolling occurred.
  98. /// - threshold: The minimum distance that must be scrolled before the title view will begin scrolling up into view
  99. func scrollViewDidScroll(_ scrollView: UIScrollView, threshold: CGFloat = 0) {
  100. contentOffset = scrollView.contentOffset.y - threshold
  101. }
  102.  
  103. // MARK: Private
  104.  
  105. private func titleVerticalPositionAdjusted(by yOffset: CGFloat) -> CGFloat {
  106. let midY = bounds.midY - label.bounds.height * 0.5
  107. return max(bounds.maxY - yOffset, midY).rounded()
  108. }
  109. }
  110.  
  111. private extension UIView {
  112. func typedSuperview<T: UIView>() -> T? {
  113. var parent = superview
  114.  
  115. while parent != nil {
  116. if let view = parent as? T {
  117. return view
  118. } else {
  119. parent = parent?.superview
  120. }
  121. }
  122.  
  123. return nil
  124. }
  125. }
Add Comment
Please, Sign In to add comment