Parallax Table View

December 22nd, 2014 3 min read

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.

Loading comments …
©2021 - MichaelTeeuw.nl