Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save cemolcay/f42a5e820a56c8bc3ab1 to your computer and use it in GitHub Desktop.
Save cemolcay/f42a5e820a56c8bc3ab1 to your computer and use it in GitHub Desktop.
Registers scroll view and label to navigation bar. Title attachs the navigation bar if scrolled out of screen
private var UIViewControllerRegisteredLabel: UInt8 = 0
private var UIViewControllerScrollTitleLabel: UInt8 = 1
extension UIViewController {
private var registeredLabel: UILabel? {
get {
return objc_getAssociatedObject(self, &UIViewControllerRegisteredLabel) as? UILabel
} set (value) {
objc_setAssociatedObject(self, &UIViewControllerRegisteredLabel, value, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
}
}
private var scrollTitleLabel: UILabel? {
get {
return objc_getAssociatedObject(self, &UIViewControllerScrollTitleLabel) as? UILabel
} set (value) {
objc_setAssociatedObject(self, &UIViewControllerScrollTitleLabel, value, UInt(OBJC_ASSOCIATION_RETAIN_NONATOMIC))
}
}
func registerScrollLabel (scroll: UIScrollView, label: UILabel) {
if let nav = navigationController {
registeredLabel = label
let container = UIView (frame: nav.navigationBar.frame)
container.y -= UIScreen.StatusBarHeight
container.clipsToBounds = true
container.tag = 10
nav.navigationBar.addSubview(container)
scrollTitleLabel = UILabel (frame: container.frame)
scrollTitleLabel?.text = label.text
scrollTitleLabel?.textColor = label.textColor
scrollTitleLabel?.textAlignment = .Center
container.addSubview(scrollTitleLabel!)
scroll.addObserver(self, forKeyPath: "contentOffset", options: .New, context: nil)
}
}
public override func observeValueForKeyPath(
keyPath: String,
ofObject object: AnyObject,
change: [NSObject : AnyObject],
context: UnsafeMutablePointer<Void>) {
let container = navigationController!.navigationBar.viewWithTag(10)!
let scroll = object as! UIScrollView
let position = scroll.convertPoint(registeredLabel!.frame.origin, toView: container)
let targetY = position.y +
scroll.contentInset.top -
registeredLabel!.frame.size.height -
scrollTitleLabel!.frame.size.height
let maxY = container.frame.size.height -
scrollTitleLabel!.frame.size.height
let y = max (targetY, maxY)
scrollTitleLabel?.frame.origin.y = y
}
}
@cemolcay
Copy link
Author

Example usage

class ViewController: UIViewController {

    var scroll: UIScrollView!

    override func viewDidLoad() {
        scroll = UIScrollView (frame: view.frame)
        view.addSubview(scroll)

        let label = UILabel (
            x: 10,
            y: 50,
            text: "Some Label",
            textColor: UIColor.blackColor(),
            textAlignment: .Left,
            font: UIFont.systemFontOfSize(15))
        scroll.addSubview(label)
        scroll.contentHeight = label.bottomWithOffset(10)

        for _ in 0...20 {
            scroll.addSubview(item (scroll.contentHeight))
            scroll.contentHeight += 160
        }

        let tit = UIView (x: 0, y: 0, w: 35, h: 30)
        tit.backgroundColor = UIColor.redColor()
        navigationItem.titleView = tit

        self.registerScrollLabel(scroll, label: label)
    }

    func item (y: CGFloat) -> UIView {
        let v = UIView (frame: CGRect (x: 10, y: y, width: view.w - 20, height: 150))
        v.backgroundColor = UIColor.randomColor()
        return v
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment