Search code examples
iosswiftuipageviewcontroller

Making beautiful transitions at PageViewController


I want to make custom transition with in PageViewController: while user moves to next slide (scroll) then background image slowly dissolves into another image.

Such effect have Apple Weather (except there is background video).

What I've done:

  • I've made UIViewContoller with background image (that image I need to change).
  • I've placed ContainerView in that UIViewController, that ContainerView have embed PageViewController. UIViewController -> ContainerView -> PageViewController

At that point I'm stuck, i have working PageViewController with shared background image (from top UIViewController), but I have no idea where to go next.

Now I can catch page changing with my delegate (main ViewContoller):

func pageChanged(currentPage: Int) {}

And default delegate method (PageViewContoller) (I have 2 slides, don't know how to do it better):

func pageViewController(pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [AnyObject], transitionCompleted completed: Bool) {
    let prevController = previousViewControllers as [ContentViewController]
    if completed {
        if prevController[0].index == 0 {
            delegate.pageChanged(1)
        } else {
            delegate.pageChanged(2)
        }
    }
}

But it is instant function, I can't do here slowly animation in dependency of user slowly swipes :).


Solution

  • I totally agree with Vasily. You need to use a UICollectionView and use self.collectionView.pagingEnabled = YES;. Then you can control perfectly the scrollview contentOffset via UIScrollViewDelegate.

    optional func scrollViewDidScroll(_ scrollView: UIScrollView)
    

    The code:

    func scrollViewDidScroll(scrollView: UIScrollView) {
    
        var currentX = scrollView.contentOffset.x
        var ratio = currentX / UIScreen.mainScreen().bounds.size.width
        var previousPageIndex = floor(ratio)
        var nextPageIndex = ceil(ratio)
        ratio = ratio - previousPageIndex
    
    }
    

    For instance, if the ratio is 0.33, the transition is 33% between the page previousPageIndex and the page nextPageIndex. You can use this values for set your alpha values in your UIImageViews:

    func scrollViewDidScroll(scrollView: UIScrollView) {
    
        var currentX = scrollView.contentOffset.x
        var ratio = currentX / UIScreen.mainScreen().bounds.size.width
        var previousPageIndex = floor(ratio)
        var nextPageIndex = ceil(ratio)
        ratio = ratio - previousPageIndex
    
        fromImageView.alpha = 1.0 - ratio;
        toImageView.alpha = ratio;
    
    }
    

    The PageViewController doesn't allow you control scrolling itself. The transition is a discrete event here. The swipe gesture is a discrete event too and you can add a smooth effect with it. The pan gesture can help you but the code will be more complex and dirty.