How to Swipe Away Navigation Bar
YouTubeToday we're back at it again with our YouTube application tutorial. I'll show you how to implement a couple of neat tricks in this video. First, we'll learn how to swipe away the navigation bar with a hidesBarsOnSwipe property. Next, we'll add a little horizontal slider bar using some iOS 9 anchor constraints to our menu bar. I'll then show you how to apply animation to this bar as you select different menu icons. Finally, we'll learn how to use completion blocks to abstract and clean out our controller code.
!codebreak
<div class='filename'>HomeController.swift</div>
!codebreak
!syntax-highlight
class HomeController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var videos: [Video]?
func fetchVideos() {
ApiService.sharedInstance.fetchVideos { (videos: [Video]) in
self.videos = videos
self.collectionView?.reloadData()
}
}
//...
private func setupMenuBar() {
navigationController?.hidesBarsOnSwipe = true
let redView = UIView()
redView.backgroundColor = UIColor.rgb(230, green: 32, blue: 31)
view.addSubview(redView)
view.addConstraintsWithFormat("H:|[v0]|", views: redView)
view.addConstraintsWithFormat("V:[v0(50)]", views: redView)
view.addSubview(menuBar)
view.addConstraintsWithFormat("H:|[v0]|", views: menuBar)
view.addConstraintsWithFormat("V:[v0(50)]", views: menuBar)
menuBar.topAnchor.constraintEqualToAnchor(topLayoutGuide.bottomAnchor).active = true
}
//...
}
!codebreak
<div class='filename'>MenuBar.swift</div>
!codebreak
!syntax-highlight
class MenuBar: UIView, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {
//...
var horizontalBarLeftAnchorConstraint: NSLayoutConstraint?
func setupHorizontalBar() {
let horizontalBarView = UIView()
horizontalBarView.backgroundColor = UIColor(white: 0.95, alpha: 1)
horizontalBarView.translatesAutoresizingMaskIntoConstraints = false
addSubview(horizontalBarView)
//old school frame way of doing things
// horizontalBarView.frame = CGRectMake(<#T##x: CGFloat##CGFloat#>, <#T##y: CGFloat##CGFloat#>, <#T##width: CGFloat##CGFloat#>, <#T##height: CGFloat##CGFloat#>)
//new school way of laying out our views
//in ios9
//need x, y, width, height constraints
horizontalBarLeftAnchorConstraint = horizontalBarView.leftAnchor.constraintEqualToAnchor(self.leftAnchor)
horizontalBarLeftAnchorConstraint?.active = true
horizontalBarView.bottomAnchor.constraintEqualToAnchor(self.bottomAnchor).active = true
horizontalBarView.widthAnchor.constraintEqualToAnchor(self.widthAnchor, multiplier: 1/4).active = true
horizontalBarView.heightAnchor.constraintEqualToConstant(4).active = true
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
print(indexPath.item)
let x = CGFloat(indexPath.item) * frame.width / 4
horizontalBarLeftAnchorConstraint?.constant = x
UIView.animateWithDuration(0.75, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .CurveEaseOut, animations: {
self.layoutIfNeeded()
}, completion: nil)
}
//...
}
!codebreak
<div class='filename'>ApiService.swift</div>
!codebreak
!syntax-highlight
class ApiService: NSObject {
static let sharedInstance = ApiService()
func fetchVideos(completion: ([Video]) -> ()) {
let url = NSURL(string: "https://s3-us-west-2.amazonaws.com/youtubeassets/home.json")
NSURLSession.sharedSession().dataTaskWithURL(url!) { (data, response, error) in
if error != nil {
print(error)
return
}
do {
let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers)
var videos = [Video]()
for dictionary in json as! [[String: AnyObject]] {
let video = Video()
video.title = dictionary["title"] as? String
video.thumbnailImageName = dictionary["thumbnail_image_name"] as? String
let channelDictionary = dictionary["channel"] as! [String: AnyObject]
let channel = Channel()
channel.name = channelDictionary["name"] as? String
channel.profileImageName = channelDictionary["profile_image_name"] as? String
video.channel = channel
videos.append(video)
}
dispatch_async(dispatch_get_main_queue(), {
completion(videos)
})
} catch let jsonError {
print(jsonError)
}
}.resume()
}
}