Creating Image Slider with UIKit APIs

Thanks to Nick Lockwood's book iOS Animation Advanced Techniques. I was able to write another implementation of Image slider. I wrote an image slider couple years back using UIScrollView for which I had to write manual routine to slide images back and forth. However, this time I used techniques iOS offered which made my task easier than before.

Using iOS to do animation means I,

  1. Don't have to write complex animation routine
  2. No need to go into mathematics to compute offset and position of an individual image
  3. No need to scroll UIScrollView manually
  4. Add extra animations to image transition with Apple built in types

I have hosted this library on Github. Excellent part of this is, it is written fully in Swift which makes it future proof too.

Here's a little demo with image slider animation,

image_slider_animation_demo

Below are the features listed.

  1. Ability to pass an array of UIImage objects which will be displayed on the view

  2. Ability to pass an array of NSURL objects which will then be downloaded from the network and shown asynchronously

  3. Ability to specify default placeholder image

Usage

Image slider is simply an UIView subclass, so you can use it like any other UIView subclass. You can embed it into your parent view and either set manual frames or add constraints.

The library provides two very similar initializers with most of the parameters set to default value so that client does not specifically need to mention all the parameters while initializing ImageSliderView

With local images,

let imageSliderView = JKImageSliderView(images: [UIImage(named: "girlRunning")!, UIImage(named: "changeColor")!, UIImage(named: "donald")!, UIImage(named: "cone")!], transitionType: kCATransitionPush, placeholderImage: UIImage(named: "placeholder"), showBullets: true)

With remote image URLs

let imageSliderView = JKImageSliderView(imageURLs: [NSURL(string: "https://pbs.twimg.com/profile_images/738744285101580288/OUoCVEXG.jpg")!, NSURL(string: "http://www.mapsofindia.com/images2/india-map.jpg")!], transitionType: kCATransitionPush, placeholderImage: UIImage(named: "placeholder"), showBullets: true)

Here is the explanation of customizable parameters,

  • images - An array of UIImage objects

  • URLs - An array of NSURL objects

  • transitionType - Types of images transitions. Possible values are,

    • kCATransitionFade
    • kCATransitionMoveIn
    • kCATransitionPush
    • kCATransitionReveal

    Effects of all these transition types are added to the demo project.

  • imageAnimationDuration - A image animation transition duration. Time it takes to change from one image to another

  • showBulletView - A flag which indicates whether to show bullet view or not. Bullet view is shown by default. It looks like below,

bullet_view

  • swipeEnabled - Indicates whether user can swipe to trigger the image transitions. Swipe gesture is disabled by default.

Getting callback when image is swiped

If client app wants to get callback for image swipe action, you can get it by confirming to following protocol,

protocol JKSliderViewDelegate: class {
    func indexChanged(to newIndex: Int)
}

Then setup the UIImageSliderView delegate to the client class in which this slider view is added, and implement the method.

imageSliderView?.delegate = self
func indexChanged(to newIndex: Int) {
    print("Slider index changed to \(newIndex)")
}

Brief Overview

This is the brief overview of how this library actually works,

// First we create the instance of `CATransition` and add appropriate properties to it,
let swipeViewTransition = CATransition()
swipeViewTransition.duration = 0.75
// How transition should occur. Possible types are listed above.
swipeViewTransition.type = kCATransitionPush
// Indicates how transition should occur. Since we are using image slider, possible types could be kCATransitionFromLeft or kCATransitionFromRight depending on the direction from which image is slid.
swipeViewTransition.subtype = kCATransitionFromLeft

// Add animation to our imageView instance
swipeImageView.layer.addAnimation(swipeViewTransition, forKey: kCATransition)

// To perform image transition, we maintain a variable named currentImageIndex. Which will keep the track of index corresponding to current image on the viewport.

// For swipe left action
currentImageIndex = currentImageIndex - 1
currentImageIndex = ((currentImageIndex % imagesCount) + imagesCount) % imagesCount

// For swipe right action
// imagesCount is an internal variable computed directly from the number of images passed to the initializer. 

currentImageIndex = currentImageIndex + 1
currentImageIndex = ((currentImageIndex % imagesCount) + imagesCount) % imagesCount

// We then update the image on the viewport depending on whether we passed plain UIImage objects or remote image URLs.

if imageType == .ImageTypeURL {              
    swipeImageView.sd_setImageWithURL(imageURLs[currentImageIndex], placeholderImage: placeHolder, options: .HighPriority)
} else {
    swipeImageView.image = images[currentImageIndex]
}

// Call the delegate if one is already setup.
if let delegate = delegate {
  delegate.indexChanged(to: currentImageIndex)
}

// Change the highlighted bullet to suitable index.

self.bulletView?.moveToIndex(currentImageIndex)

Cocoapods

This library supports integration into project through Cocoapods. Just add following line to your podfile and run pod update or pod install if pods are not already installed.

platform :ios, '8.0'
inhibit_all_warnings!
use_frameworks!

xcodeproj '<xcodeproj_file_name>'

target '<xcodeproj_file_name>' do
    pod 'JKImageSliderView', :git => 'git@github.com:jayesh15111988/JKImageSliderView.git', :tag => '0.1'/:branch => 'master'
end

For some reason I was not able to make a delegate and protocol visible to Objective-C code. My understanding is this happens if Swift type is non-bridgeable to Objective-C code. It works perfectly fine in Swift code though. If anyone has any idea why, I would appreciate their input

As usual, any comments, questions, concerns or PRs are welcome. I am looking forward to hear from you soon.