             UIView.animate(withDuration: 0.3, animations: {
                 self.setViewsToPosition(.refresh, resetContentOffset: scrollToTop)
                 self.tabBarPositionYDidChange()
-            }, completion: nil)
+            }, completion: completion)
         } else {
             setViewsToPosition(.refresh, resetContentOffset: scrollToTop)
             tabBarPositionYDidChange()
-        }
-    }
-    
-    open func minimizesTabsContent(animated: Bool, scrollToTop: Bool = true) {
-        var maximumHeight = CGFloat(0)
-        if #available(iOS 11.0, *) {
-            maximumHeight = view.frame.height - view.safeAreaInsets.top - view.safeAreaInsets.bottom - pageTabBarController.pageTabBar.frame.height
-        } else {
-            
-        }
-        setParallexHeaderHeight(maximumHeight, animated: animated, scrollToTop: scrollToTop)
-    }
+            completion?(true)
+        }
+    }
+    
+    // MARK: - Header Transitioning
+    
+    open func prepareTransition(spacing: TransitionSpacing, duration: TimeInterval, animated: Bool, completion: ((Bool) -> ())? = nil) {
+        
+        isTransitioning = true
+        
+        if revealingGapHeight != parallaxHeaderHeight {
+            scrollToTop(true) { _ in
+                self.prepareTransition(spacing: spacing, duration: duration, animated: animated, completion: completion)
+            }
+            
+            return
+        }
+        
+        let prepareCompletion: () -> () = {
+            self.headerTransitionView.isHidden = false
+        }
+        
+        var spacingHeight = CGFloat(0)
+        
+        switch spacing {
+        case .maximumSpace:
+            if #available(iOS 11.0, *) {
+                spacingHeight = view.frame.height - view.safeAreaInsets.top - view.safeAreaInsets.bottom - pageTabBarController.pageTabBar.frame.height
+            } else {
+                spacingHeight = view.frame.height - topLayoutGuide.length - bottomLayoutGuide.length - pageTabBarController.pageTabBar.frame.height
+            }
+            break
+        case let .customHeight(height):
+            spacingHeight = height
+            break
+        }
+        
+        transformTabBar(value: spacingHeight - revealingGapHeight, duration: duration, animated: true) { finished in
+            prepareCompletion()
+            completion?(finished)
+        }
+
+    }
+    
+    open func finalizeTransition(headerHeight: CGFloat, duration: TimeInterval, animated: Bool, completion: ((Bool) -> ())? = nil) {
+        
+        parallaxHeaderHeight = headerHeight
+        
+        let finalizeCompletion: () -> () = {
+            self.headerTransitionView.isHidden = true
+            self.isTransitioning = false
+        }
+        
+        if animated {
+            UIView.animate(withDuration: duration, animations: {
+                self.pageTabBarController.pageTabBar.transform = .identity
+                self.setViewsToPosition(.refresh)
+                self.tabBarPositionYDidChange()
+            }) { finished in
+                if finished {
+                    finalizeCompletion()
+                }
+                completion?(finished)
+            }
+        } else {
+            pageTabBarController.pageTabBar.transform = .identity
+            setViewsToPosition(.refresh)
+            tabBarPositionYDidChange()
+            finalizeCompletion()
+            completion?(true)
+        }
+        
+    }
+    
+    private func transformTabBar(value: CGFloat, duration: TimeInterval, animated: Bool, completion: @escaping (Bool) -> ()) {
+        
+        if animated {
+            UIView.animate(withDuration: duration, animations: {
+                self.pageTabBarController.pageTabBar.transform = CGAffineTransform(translationX: 0, y: value)
+            }, completion: completion)
+        } else {
+            pageTabBarController.pageTabBar.transform = CGAffineTransform(translationX: 0, y: value)
+            completion(true)
+        }
+        
+    }
+    
+    // MARK: - Scroll View Monitoring
     
     open func childScrollViewDidScroll(_ scrollView: UIScrollView) {
 
+        guard !isTransitioning else { return }
+        
         guard let currentScrollView = currentChildScrollViewWeakReference, currentScrollView == scrollView else { return }
         
         var contentInset = scrollView.contentInset

        case bottom
        case refresh
    }
        
    open weak var delegate: ParallaxHeaderPageTabBarControllerDelegate?
    
    open let pageTabBarController: PageTabBarController

    private weak var currentChildScrollViewWeakReference: UIScrollView?
    private var previousChildScrollViewOffset: CGPoint = .zero
    private var isLatestScrollingUp = false
    
    private var isTransitioning = false
    
    // Positions
    private var revealingGapHeight = CGFloat(0)
