Simple way to add parallax header to UIScrollView/UITableView written in Swift.

Overview

ParallaxHeader

Simple way to add parallax header to UIScrollView or it's subclasses.

One image view Slider with images Blur vibrant text Blur round icon
Demo Demo Demo Demo

Try it here

Contents

Requirements

  • iOS 8.0+
  • Xcode 8.0+
  • Swift 3.0+

Installation

CocoaPods

CocoaPods is a dependency manager for Cocoa projects. You can install it with the following command:

$ gem install cocoapods

CocoaPods 1.1.0+ is required to build Reusable 1.0.0+.

To integrate ParallaxHeader into your Xcode project using CocoaPods, specify it in your Podfile:

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '8.0'
use_frameworks!

target '<Your Target Name>' do
    pod 'ParallaxHeader', '~> 3.0.0'
end

Then, run the following command:

$ pod install

Cocoapods versions

  • Swift5 :
pod 'ParallaxHeader', '~> 3.0.0'
  • Swift4 :
pod 'ParallaxHeader', '~> 2.0.0'
  • Swift3 :
pod 'ParallaxHeader', '~> 1.0.6'

Usage

To add parallax header to scroll view (table view) you need just create view and set it to your scroll view (table view).

Use case - one image view

  //create view as header view    
  let imageView = UIImageView()
  imageView.image = UIImage(named: "1")
  imageView.contentMode = .scaleAspectFill
        
  tableView.parallaxHeader.view = imageView
  tableView.parallaxHeader.height = 400
  tableView.parallaxHeader.minimumHeight = 0
  tableView.parallaxHeader.mode = .topFill

Use case - slider of images

let parallaxHeight: CGFloat = view.frame.height - 64 - 49 - sliderHeight
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
collectionParallaxView = UICollectionView(
    frame: CGRect(x: 0, y: 0, width: view.frame.width, height: parallaxHeight),
    collectionViewLayout: layout
)
collectionParallaxView.isPagingEnabled = true
collectionParallaxView.showsHorizontalScrollIndicator = false
collectionParallaxView.backgroundColor = UIColor.white
collectionParallaxView.delegate = self
collectionParallaxView.dataSource = self

//adding view as parallax header to table view is straightforward
tableView.parallaxHeader.view = collectionParallaxView
tableView.parallaxHeader.height = parallaxHeight
tableView.parallaxHeader.minimumHeight = 0
tableView.parallaxHeader.mode = .centerFill
tableView.parallaxHeader.parallaxHeaderDidScrollHandler = { parallaxHeader in
    print(parallaxHeader.progress)
}

Use case - Blur vibrant text

  • Blur library is used here.
  • SnapKit library is used here.
let imageView = UIImageView()
imageView.image = UIImage(named: "profile")
imageView.contentMode = .scaleAspectFill
        
//setup blur vibrant view
imageView.blurView.setup(style: UIBlurEffectStyle.dark, alpha: 1).enable()
        
headerImageView = imageView
        
tableView.parallaxHeader.view = imageView
tableView.parallaxHeader.height = 400
tableView.parallaxHeader.minimumHeight = 40
tableView.parallaxHeader.mode = .centerFill
tableView.parallaxHeader.parallaxHeaderDidScrollHandler = { parallaxHeader in
    //update alpha of blur view on top of image view 
    parallaxHeader.view.blurView.alpha = 1 - parallaxHeader.progress
}
        
// Label for vibrant text
let vibrantLabel = UILabel()
vibrantLabel.text = "Vibrant"
vibrantLabel.font = UIFont.systemFont(ofSize: 40.0)
vibrantLabel.sizeToFit()
vibrantLabel.textAlignment = .center
imageView.blurView.vibrancyContentView?.addSubview(vibrantLabel)
//add constraints using SnapKit library
vibrantLabel.snp.makeConstraints { make in
    make.edges.equalToSuperview()
}

Use case - Blur round icon

  • Blur library is used here.
  • SnapKit library is used here.
let image = UIImage(named: "profile")
        
let imageView = UIImageView()
imageView.image = image
imageView.contentMode = .scaleAspectFill
parallaxHeaderView = imageView
        
//setup bur view
imageView.blurView.setup(style: UIBlurEffectStyle.dark, alpha: 1).enable()
        
tableView.parallaxHeader.view = imageView
tableView.parallaxHeader.height = 400
tableView.parallaxHeader.minimumHeight = 120
tableView.parallaxHeader.mode = .centerFill
tableView.parallaxHeader.parallaxHeaderDidScrollHandler = { parallaxHeader in
    //update alpha of blur view on top of image view
    parallaxHeader.view.blurView.alpha = 1 - parallaxHeader.progress
}
        
let roundIcon = UIImageView(
    frame: CGRect(x: 0, y: 0, width: 100, height: 100)
)
roundIcon.image = image
roundIcon.layer.borderColor = UIColor.white.cgColor
roundIcon.layer.borderWidth = 2
roundIcon.layer.cornerRadius = roundIcon.frame.width / 2
roundIcon.clipsToBounds = true
        
//add round image view to blur content view
//do not use vibrancyContentView to prevent vibrant effect
imageView.blurView.blurContentView?.addSubview(roundIcon)
//add constraints using SnpaKit library
roundIcon.snp.makeConstraints { make in
    make.center.equalToSuperview()
    make.width.height.equalTo(100)
}

Author

Roman Sorochak - iOS developer - [email protected]

License

ParallaxHeader is released under the MIT license. See LICENSE for details.

Comments
  • Cannot Use Header Sections In a UITableView

    Cannot Use Header Sections In a UITableView

    Using the parallax header with a UITableView that has header sections causes scrolling issues with the header sticking in the view until scrolling to another header section.

    class UserHomeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    
        var tabBar:TabBar?
        let sections = ["Drafts", "Scheduled", "Past"]
        
        @IBOutlet weak var eventsTableView: UITableView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            initUI()
        }
        
        /// Initialize any UI components
        private func initUI(){
            initTableView()
            tabBar = TabBar.init(self.view, navController: self.navigationController!, isVendor: false, selectedTab: 0)
        }
    
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
        }
        
        /// Initialize the trip table view
        fileprivate func initTableView(){
            
            eventsTableView.register(UINib(nibName: "TripTableViewCell", bundle: nil), forCellReuseIdentifier: "TripTableViewCell")
            eventsTableView.rowHeight = 60
                   
            eventsTableView.parallaxHeader.view = (Bundle.main.loadNibNamed("ParallaxHeaderView", owner: self, options: nil)![0] as? UIView)!
            eventsTableView.parallaxHeader.height = 120
            eventsTableView.parallaxHeader.minimumHeight = 0
            eventsTableView.parallaxHeader.mode = .topFill
        }
        
        /// Set the number of entries in table view
        /// - parameter tableView: table view we are getting the size of.
        /// - parameter section: section of the table view we are getting the size of.
        /// - returns: the size of the table view.
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            
            var size = 0
            
            switch section {
            case 0:
                size = 5
            case 1:
                size = 5
            case 2:
                size = 5
            default:
                size = 0
            }
            
            return size
        }
        
        /// Set the values for the table view cells
        /// - parameter tableView: table view that the cell is being initialized for.
        /// - parameter indexPath: row in the table view that the cell will be placed.
        /// - returns: the initialized table view cell.
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            
            let cell = tableView.dequeueReusableCell(withIdentifier: "TripTableViewCell", for: indexPath) as! TripTableViewCell
            
            return cell
        }
        
        func numberOfSections(in tableView: UITableView) -> Int {
            return sections.count
        }
        
        func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
            return 30.0
        }
        
        func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
            
            let header = Bundle.main.loadNibNamed("EventsHeaderView", owner: self, options: nil)![0] as! EventsHeaderView
            header.headerLabel.text = sections[section]
            
            return header
        }
    }
    
    opened by MattFlood7 3
  • hold header in bottom of UINavigationBar [ iOS 10 ]

    hold header in bottom of UINavigationBar [ iOS 10 ]

    Hi, Thanks for this amazing library i've noticed there's an issue with iOS 10 when scroll to top and when navigation bar is Translucent

    You can see the different bellow

    iOS 11 - Working correctly screen shot 2018-02-13 at 10 59 49 am iOS 10 - has an issue screen shot 2018-02-13 at 11 00 36 am

    opened by ahmedraad 2
  • Swift 4.2 syntax conversion

    Swift 4.2 syntax conversion

    Hello, I completed conversion to swift 4.2.

    I tested everything and it works fine. Please accept pull request if it's possible.

    @romansorochak

    And thanks for nice project!

    opened by itruf 1
  • iOS 10 Status bar issue

    iOS 10 Status bar issue

    Hi All,

    I'm having having an issue where the header is shown bellow the status bar. So the header.y == statubar.maxY. The tableview's.y == 0. So the content is shown bellow the status bar. Can anyone help?

    Thanks in advance!

    opened by fabiangiger 1
  • Scroll To Row results in scrolling to bottom of UITableView

    Scroll To Row results in scrolling to bottom of UITableView

    Hi, I'm implementing a comments tableview with a parallax header. To show insertion of comments I'm using scrollToRow but when I use it on a tableView with parallax header, the table is scrolled down to the bottom. I've tested it without parallax header scrolling works exactly as needed. Also my table style is plain and I'm using a section header as a comment having replies as cells.

    opened by imwinit 0
  • Fix constraint error for 'center' and 'centerFill'

    Fix constraint error for 'center' and 'centerFill'

    Hi 👋

    Thanks for your awesome library! 👍 I just notice a small constraint error. If you:

    1. Launch your example project
    2. Test one tableView with parallaxHeader using centerFill as mode
    3. You'll see an error in the logs "Unable to satisfy constraint... attempt recovering by breaking constraint centerX"

    I fixed it! Works like a charm ✨

    opened by kevin-hirsch 0
  • Ignore top safe area insets if needed for headers which cover the whole NavigationBar.

    Ignore top safe area insets if needed for headers which cover the whole NavigationBar.

    Issue: Safe area is been used to pin contentView without taking into consideration some of other custom layouts, for example having an imageView as header covering the whole navBar including safeAreas.

    This PR adds an optional flag were users can set it to true if their headers fill the whole safe area.

     /// This is to support a usecase where a parallax header is being used at the very top edge of the screen.
    /// If this is set to true then the header will be pinned at the top of the scrollView. Default value is `false`
        public var ignoreTopSafeAreaInset:Bool = false
    

    Usage: myScrollview.parallaxHeader.ignoreTopSafeAreaInset = true

    NB: This is somewhat similar to this PR but the only difference is that this one doesn't break any previous intended behavior by the original author. It only apply the changes if user needs them by manually setting ignoreTopSafeAreaInset to true.

    opened by MussaCharles 0
  • Revert

    Revert "fix safeAreaInsets for iOS 11"

    This reverts commit 77814dc61a2715a76f6f537d6de44e613d927060.

    We're using the parallax header on the very top of one of our screens. This change leads to a top offset (44pt) on newer "notch devices" as we don't want to constraint to the safeArea but, to the very top of the screen.

    opened by d4rkd3v1l 1
  • Scroll To Row results in scrolling to bottom of UITableView

    Scroll To Row results in scrolling to bottom of UITableView

    Hi, I'm implementing a comments tableview with a parallax header. To show insertion of comments I'm using scrollToRow but when I use it on a tableView with parallax header, the table is scrolled down to the bottom. I've tested it without parallax header scrolling works exactly as needed. Also my table style is plain and I'm using a section header as a comment having replies as cells. I've tested this in MXParallaxHeader too and it also produces same problem. Kindly let me know if anything I'm missing here or if you can relate the issue. Thanks

    opened by imwinit 1
  • compatible for swift 5

    compatible for swift 5

    hi there , recently I updated my app and is giving me some syntax changes , I was able to unlock your code to make them, but it would be super awesome If you could take some of your time to make it avalaiable for swift 5 please

    opened by KevsAlex 1
Owner
Roman Sorochak
Roman Sorochak
Pull-to-refresh animation in UICollectionView with a sticky header flow layout, written in Swift :large_orange_diamond:

ReplaceAnimation Implementation of Zee Young's Dribbble animation (https://dribbble.com/shots/2067564-Replace) Info I really liked Zee Young's animati

Alex Türk 957 Sep 13, 2022
The fastest and easiest way to present a UITableView - in 3 lines of code.

Swift Table The fastest and easiest way to present a UITableView - in 3 lines of code. Powered by Generics to present any data type. No need to use th

Benyam Alemu Sood 14 Sep 19, 2022
Give pull-to-refresh & infinite scrolling to any UIScrollView with 1 line of code.

SVPullToRefresh + SVInfiniteScrolling These UIScrollView categories makes it super easy to add pull-to-refresh and infinite scrolling fonctionalities

Sam Vermette 4.9k Sep 10, 2022
PullToRefresh extension for all UIScrollView type classes with animated text drawing style

PullToRefreshCoreText PullToRefresh extension for all UIScrollView type classes with animated text drawing style Demo Install Manual Copy the files in

Cem Olcay 313 Jun 29, 2022
Custom animated pull-to-refresh that can be easily added to UIScrollView

PullToMakeSoup Custom animated pull-to-refresh that can be easily added to UIScrollView Check this article on our blog to know more details about anim

Yalantis 1.9k Sep 2, 2022
Animated "Pull To Refresh" Library for UIScrollView.

PullToBounce Animated "Pull To Refresh" Library for UIScrollView. You can add animated "pull to refresh" action to your UIScrollView, UITableView and

Takuya Okamoto 1.9k Sep 18, 2022
LCPullRefresh - Use UIActivityIndicatorView to provide a pull-to-refresh function for UIScrollView.

LCPullRefresh Use UIActivityIndicatorView to provide a pull-to-refresh function for UIScrollView. Requirements iOS 8.0+ Xcode 11.0+ Usage Pull-up refr

LiuChang 7 Aug 5, 2022
DGDynamicHeightTableView - UITableView that supports auto calculated height by contents size

DGDynamicHeightTableView UITableView that supports auto calculated height by con

donggyu 6 Jul 22, 2022
Add PullToRefresh using animated GIF to any scrollView with just simple code

UzysAnimatedGifPullToRefresh Add PullToRefresh using animated GIF to any scrollView with just simple code UzysAnimatedGifPullToRefresh features: simpl

Jaehoon Jung 1.4k Sep 20, 2022
iOS Simple Cool PullToRefresh Library. It is written in pure swift.

PullToRefreshSwift iOS Simple PullToRefresh Library. ##Installation ####CocoaPods pod 'PullToRefreshSwift' ####Manually Add the following files to yo

Yuji Hato 534 Jun 29, 2022
An easy way to use pull-to-refresh.

MJRefresh An easy way to use pull-to-refresh ?? ✍??Release Notes: more details Contents New Features Dynamic i18n Switching SPM Supported Swift Chaini

M了个J 13.7k Sep 18, 2022
An easy way to use pull-to-refresh

CRRefresh an easy way to use pull-to-refresh, If you want to customize its UI style, you just need conform the specified protocol. We will not regular

CRAnimation 934 Aug 29, 2022
Customizable pull-to-refresh control,written in pure Swift.

What is it This project is heavily inspired by CBStoreHouseRefreshControl which is Objective-C implemented. SurfingRefreshControl provides you a chanc

Peiwei 55 Aug 21, 2022
Simple refresh control for iOS based on SpriteKit and Core Graphics

RainyRefreshControl Simple refresh control for iOS based on SpriteKit and Core Graphics. Project inspired by concept of Yup Nguyen Installation Instal

Onix-Systems 679 Sep 9, 2022
API-TableView-Swift - API call with URLSession and show data to TableView with swift

API-TableView-Swift API call with URLSession and show data to TableView with swi

Aman Ullah Akhand 1 Sep 3, 2022
Elastic pull to refresh for iOS developed in Swift

DGElasticPullToRefresh Elastic pull to refresh compontent developed in Swift Inspired by this Dribbble post: Pull Down to Refresh by Hoang Nguyen Tuto

Danil Gontovnik 3.7k Sep 23, 2022
Recipe App TableView Using Swift

RecipeApp---TableView Features in Food Recipe App User Login search for recipes View recipe lists View Steps tutorials for recipes Like recipes In app

Hardik 3 Apr 27, 2022
UICollectionView replacement of UITableView. Do even more like Parallax Header, Sticky Section Header. Made for iOS 7.

CSStickyHeaderFlowLayout Contributors For anyone who'd like to be a contributor to the repository, please read the Contribution Guideline Parallax, St

null 5.1k Sep 18, 2022
Simple parallax header for UIScrollView

MXParallaxHeader ⚠️ This project is no longer maintained, see #124 ⚠️ MXParallaxHeader is a simple header class for UIScrollView. In addition, MXScrol

Maxime Epain 1.7k Sep 21, 2022
HPParallaxHeader is a simple parallax header class for UIScrollView.

HPParallaxHeader is a simple parallax header class for UIScrollView.

null 37 Aug 11, 2022