Vasily Vasily - 1 month ago 17
iOS Question

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 :).

Answer

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.

Comments