A lot of iOS Apps nowadays use table views with images as a header. Yahoo News Digest is a good example, but misses a parallax effect to make it a bit less ordinary. I wanted to check out how simple it is to create such a Table View in Swift.
The Yahoo News Digest App
To start off, I needed to subclass a UITableView:
class ParallaxTableViewController: UITableViewController {
... // all following code goes here
}
Of course, this subclassed Table View needs an UIImageView to hold the image, and some variables to set some properties:
// Create the UIImageView
let imageView = UIImageView()
// Set the factor for the parallaxEffect. This is overwritable.
var parallaxFactor:CGFloat = 2
// Set the default height for the image on the top.
var imageHeight:CGFloat = 300 {
didSet {
moveImage()
}
}
// Initialize the scrollOffset variable.
var scrollOffset:CGFloat = 0 {
didSet {
moveImage()
}
}
When we load this TableView the contentInset of the Table View is changed to make room for the image. Then we add the Image View to the view:
override func viewDidLoad() {
super.viewDidLoad()
// Set the contentInset to make room for the image.
self.tableView.contentInset = UIEdgeInsets(top: imageHeight, left: 0, bottom: 0, right: 0)
// Change the contentMode for the ImageView.
imageView.contentMode = UIViewContentMode.ScaleAspectFill
// Add the imageView to the TableView and send it to the back.
view.addSubview(imageView)
view.sendSubviewToBack(imageView)
}
We define a method to adjust the location of the Image View according to the current scroll offset:
// Define method for image location changes.
func moveImage() {
let imageOffset = (scrollOffset >= 0) ? scrollOffset / parallaxFactor : 0
let imageHeight = (scrollOffset >= 0) ? self.imageHeight : self.imageHeight - scrollOffset
imageView.frame = CGRect(x: 0, y: -imageHeight + imageOffset, width: view.bounds.width, height: imageHeight)
}
This message is called when the subviews are layout, or when the table view scrolls:
override func viewDidLayoutSubviews() {
// Update the image position after layout changes.
moveImage()
}
// Update scrollOffset on tableview scroll
override func scrollViewDidScroll(scrollView: UIScrollView) {
scrollOffset = tableView.contentOffset.y + imageHeight
}
Note that no actial image is set to the UIImageView. The best place to do this, is in a subclass of the ParallaxTableViewController
. I posted an example on GitHub that results in the following effect:
Feel free to grab the code on GitHub. Any ideas on how to improve it? Leave a comment down below or send me a pull request.