How to autoscroll the scrollView horizontally? - ios

I am using this code to scroll the scrollview horizontally when sliding the scrollview.
func getScrollView() {
upperScroll.delegate = self
upperScroll.isPagingEnabled = true
// pageControll.numberOfPages = logoImage.count
upperScroll.isScrollEnabled = true
let scrollWidth: Int = Int(self.view.frame.width)
upperScroll.contentSize = CGSize(width: CGFloat(scrollWidth), height:(self.upperScroll.frame.height))
print(upperScroll.frame.size.width)
upperScroll.backgroundColor = UIColor.clear
for index in 0..<logoImage.count {
let xPosition = self.view.frame.width * CGFloat(index)
upperScroll.layoutIfNeeded()
let img = UIImageView(frame: CGRect(x: CGFloat(xPosition), y: 0, width: upperScroll.frame.size.width, height: self.upperScroll.frame.height))
img.layoutIfNeeded()
let str = logoImage[index]
let url = URL(string: str)
img.sd_setImage(with: url, placeholderImage: UIImage(named:"vbo_logo2.png"))
upperScroll.addSubview(img)
}
view.addSubview(upperScroll)
upperScroll.contentSize = CGSize(width: CGFloat((scrollWidth) * logoImage.count), height: self.upperScroll.frame.height)
}
But i want to auto scroll?
How can i do this. Can anyone help me please.

I got the solution
#objc func animateScrollView() {
let scrollWidth = upperScroll.bounds.width
let currentXOffset = upperScroll.contentOffset.x
let lastXPos = currentXOffset + scrollWidth
if lastXPos != upperScroll.contentSize.width {
print("Scroll")
upperScroll.setContentOffset(CGPoint(x: lastXPos, y: 0), animated: true)
}
else {
print("Scroll to start")
upperScroll.setContentOffset(CGPoint(x: 0, y: 0), animated: true)
}
}
func scheduledTimerWithTimeInterval(){
// Scheduling timer to Call the function "updateCounting" with the interval of 1 seconds
timer = Timer.scheduledTimer(timeInterval: 10, target: self, selector: #selector(self.animateScrollView), userInfo: nil, repeats: true)
}
and call this function in ViewDidAppear

https://developer.apple.com/documentation/uikit/uiscrollview/1619400-setcontentoffset?language=objc
func scrollToPoint(point: CGPoint) {
DispatchQueue.main.asyncAfter(deadline: .now() + .seconds(10.0)) {
upperScroll.setContentOffset(point/* where you want to scroll to*/, animated:true)
}
}
you can specify the x axis when you are creating the point to pass to the func:
CGPoint(x: 100, y: 0)

There are method available to scroll for visible rect in scrollView. You need to pass CGRect in method, this means area where you want to scroll.
- (void)scrollRectToVisible:(CGRect)rect animated:(BOOL)animated;

How about that:
let timer = Timer.scheduledTimer(timeInterval: 2, target: self, selector: (#selector(ViewController.timerAction)), userInfo: nil, repeats: true)
#objc func timerAction() {
var xOffSet = 0
xOffSet += 10
UIView.animateWithDuration(1, delay: 0, options: UIViewAnimationOptions.CurveLinear, animations: {
self.scrollView.contentOffset.x = xOffSet
}, completion: nil)
}
How to implement auto scroll in UIScrollview using Swift 3?

Related

make UIImageView fall

I've UIImageview with its own position, after clicking that ( done with tapgesture ) I want that view to fall to ground until the position is 0. I tried making it with while loop but doesn't seem to work. any soltuions ?
var bananaView = UIImageView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
#objc func handleTap(_ sender:UITapGestureRecognizer) {
let centerPosition = bananaView.frame.origin.y
while centerPosition >= 0 {
bananaView.layer.position = CGPoint(x: 0,y : centerPosition - 1)
}
}
You set the new position (0) for it. Then you wrap the layout update inside an animation block
#objc func handleTap(_ sender:UITapGestureRecognizer) {
let centerPosition = bananaView.frame.origin.y
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: true) { timer in
if bananaView.frame.origin.y - bananaView.frame.height == 0 {
timer.invalidate()
} else {
bananaView.frame.origin.y -= 1
}
}
}

iOS Spin UIImageView with deceleration motion at random position

I trying to create a spin wheel which rotate on tap and it rotates for certain period of time and stops at some random circular angle.
import UIKit
class MasterViewController: UIViewController {
lazy var imageView: UIImageView = {
let bounds = self.view.bounds
let v = UIImageView()
v.backgroundColor = .red
v.frame = CGRect(x: 0, y: 0,
width: bounds.width - 100,
height: bounds.width - 100)
v.center = self.view.center
return v
}()
lazy var subView: UIView = {
let v = UIView()
v.backgroundColor = .black
v.frame = CGRect(x: 0, y: 0,
width: 30,
height: 30)
return v
}()
var dateTouchesEnded: Date?
var dateTouchesStarted: Date?
var deltaAngle = CGFloat(0)
var startTransform: CGAffineTransform?
var touchPointStart: CGPoint?
override func viewDidLoad() {
super.viewDidLoad()
self.imageView.addSubview(self.subView)
self.view.addSubview(self.imageView)
self.imageView.isUserInteractionEnabled = true
self.setupGesture()
}
private func setupGesture() {
let gesture = UITapGestureRecognizer(target: self,
action: #selector(handleGesture(_:)))
self.view.addGestureRecognizer(gesture)
}
#objc
func handleGesture(_ sender: UITapGestureRecognizer) {
var timeDelta = 1.0
let _ = Timer.scheduledTimer(withTimeInterval: 0.2,
repeats: true) { (timer) in
if timeDelta < 0 {
timer.invalidate()
} else {
timeDelta -= 0.03
self.spinImage(timeDelta: timeDelta)
}
}
}
func spinImage(timeDelta: Double) {
print("TIME DELTA:", timeDelta)
let direction: Double = 1
let rotation: Double = 1
UIView.animate(withDuration: 5,
delay: 0,
options: .curveEaseOut,
animations: {
let transform = self.imageView.transform.rotated(
by: CGFloat(direction) * CGFloat(rotation) * CGFloat(Double.pi)
)
self.imageView.transform = transform
}, completion: nil)
}
}
I tried via above code, but always stops on initial position
i.e. the initial and final transform is same.
I want it to be random at every time.
One thing you can do is make a counter with a random number within a specified range. When the time fires, call spinImage then decrement the counter. Keep doing that until the counter reaches zero. This random number will give you some variability so that you don't wind up with the same result every time.
#objc func handleGesture(_ sender: UITapGestureRecognizer) {
var counter = Int.random(in: 30...33)
let _ = Timer.scheduledTimer(withTimeInterval: 0.2, repeats: true) { (timer) in
if counter < 0 {
timer.invalidate()
} else {
counter -= 1
self.spinImage()
}
}
}
In spinImage, instead of rotating by CGFloat.pi, rotate by by CGFloat.pi / 2 so that you have four possible outcomes instead of two.
func spinImage() {
UIView.animate(withDuration: 2.5,
delay: 0,
options: .curveEaseOut,
animations: {
let transform = self.imageView.transform.rotated(
by: CGFloat.pi / 2
)
self.imageView.transform = transform
}, completion: nil)
}
You may want to mess around with the counter values, the timer interval, and the animation duration to get the effect that you want. The values I chose here are somewhat arbitrary.

Move scrollview automatically with page controller

Hi I am using the PageController in my application.
I have inserted all the data on scrollView.
What I want do is, I want to move the scrollview automatically like page control with specific time.
When the scrollView reaches to last page it again recall all pages speedy and start from first onwards.
I want to load/get first page very smoothly after last page completion.
Find my code with following.
var slides:[Slide] = [];
var offSet: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
slides = createSlides()
setupSlideScrollView(slides: slides)
pageControl.numberOfPages = slides.count
pageControl.currentPage = 0
view.bringSubview(toFront: pageControl)
let timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(autoScroll), userInfo: nil, repeats: true)
}
#objc func autoScroll() {
let totalPossibleOffset = CGFloat(slides.count - 1) * self.view.bounds.size.width
if offSet == totalPossibleOffset {
offSet = 0 // come back to the first image after the last image
}
else {
offSet += self.view.bounds.size.width
}
DispatchQueue.main.async() {
UIView.animate(withDuration: 0.3, delay: 0, options: UIViewAnimationOptions.curveLinear, animations: {
self.scrollView.contentOffset.x = CGFloat(self.offSet)
}, completion: nil)
}
}
#objc func autoScroll() {
let totalPossibleOffset = CGFloat(slides.count - 1) * self.view.bounds.size.width
if offSet == totalPossibleOffset {
offSet = 0 // come back to the first image after the last image
}
else {
offSet += self.view.bounds.size.width
}
DispatchQueue.main.async() {
UIView.animate(withDuration: 0.1, delay: 0, options: UIView.AnimationOptions.curveLinear, animations: {
self.scrollView.scroll(topOffset:offSet, animated: true)
}, completion: nil)
}
}
extension UIScrollView {
// Bonus: Scroll
func scroll(topOffset:Float, animated: Bool) {
let ofSetValue = CGPoint(x: topOffset, y: 0)
setContentOffset(ofSetValue, animated: animated)
}
}
Use the following code working fine.
#objc func autoScroll() {
let totalPossibleOffset = CGFloat(slides.count - 1) * self.view.bounds.size.width
if offSet == totalPossibleOffset {
offSet = 0 // come back to the first image after the last image
}
else {
offSet += self.view.bounds.size.width
}
DispatchQueue.main.async() {
UIView.animate(withDuration: 0.0, delay: 0, options: UIViewAnimationOptions.curveLinear, animations: {
self.scrollView.contentOffset.x = CGFloat(self.offSet)
}, completion: nil)
}
}

Reset UIProgressView and begin animating immediately with Swift 3

I have a progress view like the one Snapchat and Instagram Stories have. My content changes after the progress view reaches to the end or when tapped on a button.
I'm reseting the progress view when content changes. Everything works as expected while there is no intervention. But when tapped on next button the progress view doesn't start again until the other loop executes.
You can see the video here quickly.
I came across this question while I was researching, I have the same scenario but I couldn't apply the principle as a newbie with swift 3.
Here is my code, any help would be highly appreciated:
func startTimer(){
self.timer = Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(myVievController.nextItem), userInfo: nil, repeats: false)
}
func updateProgressBar() {
self.progressView.setProgress(1.0, animated: false)
UIView.animate(withDuration: 2.8, animations: {() -> Void in
self.progressView.layoutIfNeeded()
}, completion: { finished in
if finished {
self.progressView.setProgress(0, animated: false)
}
})
}
func nextItem(){
// ...
self.updateUI(item: self.myCurrentItem)
// ...
}
func updateUI(item:MyItem){
self.updateProgressBar()
self.timer.invalidate()
self.startTimer()
// Clear old item and fill new values etc...
}
#IBAction func nextButtonPressed(_ sender: UIButton) {
self.nextItem()
}
Could also do it with a subclass:
class HelloWorld: UIProgressView {
func startProgressing(duration: TimeInterval, resetProgress: Bool, completion: #escaping (Void) -> Void) {
stopProgressing()
// Reset to 0
progress = 0.0
layoutIfNeeded()
// Set the 'destination' progress
progress = 1.0
// Animate the progress
UIView.animate(withDuration: duration, animations: {
self.layoutIfNeeded()
}) { finished in
// Remove this guard-block, if you want the completion to be called all the time - even when the progression was interrupted
guard finished else { return }
if resetProgress { self.progress = 0.0 }
completion()
}
}
func stopProgressing() {
// Because the 'track' layer has animations on it, we'll try to remove them
layer.sublayers?.forEach { $0.removeAllAnimations() }
}
}
This can be used by calling -startProgressing() when ever you need to start the progressView again from the start. The completion is called when it has finished the animation, so you can change the views etc.
An example of use:
progressView.startProgressing(duration: 5.0, resetProgress: true) {
// Set the next things you need... change to a next item etc.
}
You probably need something like this to update your progress bar: self.progressView.setProgress(0, animated: false)
func updateProgressBar() {
DispatchQueue.main.async {
self.progressView.setProgress(0.1, animated: false)
}
if self.progressView.Progress == 1.0 {
self.timer.invalidate()
} else {
self.timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(myVievController.updateProgressBar), userInfo: nil, repeats: false)
}
}
Then you can invalidate the timer and stop the update when you are at 100%
Example
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var progressView: UIProgressView!
var timer : Timer?
var timerCount = 0
var imageArray : Array<UIImage> = []
// MARK: - Lifecycle -
override func viewDidLoad() {
super.viewDidLoad()
// create gradient images
buildImageArray(duration: 3, highlightPercentage: 10.0, mainColor: .green, highlightColor: .yellow, imageWidth: Double(progressView.frame.width))
// set progressView to first image
progressView.progressImage = imageArray[0]
// set progressView progress
progressView.progress = 0.7
// schedule timer
if self.timer == nil {
self.timer = Timer.scheduledTimer(timeInterval: 1/60, target: self, selector: #selector(updateGradient), userInfo: nil, repeats: true)
RunLoop.main.add(self.timer!, forMode: .common)
}
}
func buildImageArray(duration: Int, highlightPercentage: Double, mainColor: UIColor, highlightColor: UIColor, imageWidth: Double){
let keyFrames = duration * 60
for i in 0..<keyFrames {
// Drawing code
let frame = CGRect(x: 0.0, y: 0.0, width: imageWidth, height: 1.0)
let layer = CAGradientLayer()
layer.frame = frame
layer.startPoint = CGPoint(x: 0.0, y: 0.5)
layer.endPoint = CGPoint(x: 1.0, y: 0.5)
var colors : [UIColor] = []
for n in 0..<keyFrames {
colors.append(mainColor)
}
let highlightKeyFrames : Int = Int(floor(Double(keyFrames) * (highlightPercentage/100)))
// 300 * .3 = 90 kf
for x in 0..<highlightKeyFrames {
let p = i+x
if p < keyFrames {
colors[p] = highlightColor
}
}
layer.colors = colors.map { $0.cgColor }
layer.bounds = frame
let image = UIImage.imageWithLayer(layer: layer)
imageArray.append(image)
}
}
// updateGradient
#objc func updateGradient(){
// crop image to match progress
let newWidth = self.progressView.frame.width * CGFloat(progressView.progress)
let progressImage = imageArray[timerCount].crop(rect: CGRect(x: 0, y: 0, width: newWidth, height: 1))
progressView.progressImage = progressImage
// increment timer
timerCount = timerCount + 1
if timerCount >= imageArray.count {
timerCount = 0
}
}
}
extension UIImage {
class func imageWithLayer(layer: CALayer) -> UIImage {
UIGraphicsBeginImageContextWithOptions(layer.bounds.size, layer.isOpaque, 0.0)
layer.render(in: UIGraphicsGetCurrentContext()!)
let img = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return img!
}
func crop( rect: CGRect) -> UIImage {
var rect = rect
rect.origin.x*=self.scale
rect.origin.y*=self.scale
rect.size.width*=self.scale
rect.size.height*=self.scale
let imageRef = self.cgImage!.cropping(to: rect)
let image = UIImage(cgImage: imageRef!, scale: self.scale, orientation: self.imageOrientation)
return image
}
}

Image Slideshow Swift ios

I'm new to ios development. I am trying to make a simple fullscreen image slide show. On swipe left, the slideshow should show the next image, and swipe right the slideshow should show the previous image.
I have it working, however, if I swipe in quick succession, I get a blank screen, almost as if the animations aren't keeping up, and then when I wait a moment and swipe again the image views speed up into place and works normally again. Any idea what I'm doing wrong? What is the best practice when it comes to implementing an image carousel like this with a dynamic amount of images (here they're hardcoded)?
import UIKit
var imageArr = ["imageOne.jpg", "imageTwo.jpg", "imageThree.jpg", "imageFour.jpg", "imageFive.jpg"]
var imageIndex = 0;
class ViewController: UIViewController {
var currImage = UIImageView()
var rightImage = UIImageView()
var leftImage = UIImageView()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var bounds:CGRect = UIScreen.mainScreen().bounds
var width:CGFloat = bounds.size.width
var height:CGFloat = bounds.size.height
currImage.frame = CGRect(x: 0.0, y: 0.0, width: width, height: height)
currImage.image = UIImage(named: imageArr[imageIndex])
rightImage.frame = CGRect(x: width, y: 0.0, width: width, height: height)
rightImage.image = UIImage(named: imageArr[imageIndex + 1])
leftImage.frame = CGRect(x: -width, y: 0.0, width: width, height: height)
leftImage.image = UIImage(named: imageArr[imageArr.count - 1])
self.view.addSubview(currImage)
self.view.addSubview(rightImage)
self.view.addSubview(leftImage)
var swipeLeft = UISwipeGestureRecognizer(target: self, action: "handleSwipe:")
swipeLeft.direction = UISwipeGestureRecognizerDirection.Left
self.view.addGestureRecognizer(swipeLeft)
var swipeRight = UISwipeGestureRecognizer(target: self, action: "handleSwipe:")
swipeRight.direction = UISwipeGestureRecognizerDirection.Right
self.view.addGestureRecognizer(swipeRight)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
let transitionManager = TransitionManager()
func handleSwipe(gesture: UIGestureRecognizer) {
var bounds:CGRect = UIScreen.mainScreen().bounds
var width:CGFloat = bounds.size.width
var height:CGFloat = bounds.size.height
if let swipeGesture = gesture as? UISwipeGestureRecognizer {
if (swipeGesture.direction == UISwipeGestureRecognizerDirection.Left ) {
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.2, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.currImage.frame = CGRect(x: -width, y: 0.0, width: width, height: height)
self.rightImage.frame = CGRect(x: 0.0, y:0.0, width: width, height: height)
}, completion: { finished in
if (!finished) { return }
imageIndex++
imageIndex = imageIndex <= imageArr.count-1 ? imageIndex : 0
var leftIndex = imageIndex - 1 < 0 ? imageArr.count - 1 : imageIndex - 1
self.leftImage.image = UIImage(named: imageArr[leftIndex])
self.leftImage.frame = CGRect(x: -width, y: 0.0, width: width, height: height)
var tempImg = self.currImage
self.currImage = self.rightImage
self.rightImage = tempImg
self.rightImage.frame = CGRect(x: width, y: 0.0, width: width, height: height)
var rightIndex = imageIndex + 1 > imageArr.count - 1 ? 0 : imageIndex + 1
self.rightImage.image = UIImage(named: imageArr[rightIndex])
})
}
if (swipeGesture.direction == UISwipeGestureRecognizerDirection.Right) {
UIView.animateWithDuration(0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0.2, options: UIViewAnimationOptions.CurveEaseIn, animations: {
self.currImage.frame = CGRect(x: width, y: 0.0, width: width, height: height)
self.leftImage.frame = CGRect(x: 0.0, y: 0.0, width: width, height: height)
}, completion: { finished in
imageIndex--
imageIndex = imageIndex < 0 ? imageArr.count - 1 : imageIndex
var rightIndex = imageIndex + 1 > imageArr.count - 1 ? 0 : imageIndex + 1
self.rightImage.image = UIImage(named: imageArr[rightIndex])
self.rightImage.frame = CGRect(x: width, y: 0.0, width: width, height: height)
var tempImg = self.currImage
self.currImage = self.tempImg
self.leftImage = tempCurr
self.leftImage.frame = CGRect(x: -width, y: 0.0, width: width, height: height)
var leftIndex = imageIndex - 1 < 0 ? imageArr.count - 1 : imageIndex - 1
self.leftImage.image = UIImage(named: imageArr[leftIndex])
})
}
}
}
}
Any help is much appreciated!
#IBOutlet weak var imageView:UIImageView!
var i=Int()
override func viewDidLoad() {
super.viewDidLoad()
Timer.scheduledTimer(timeInterval: 3.0, target: self, selector: #selector(imageChange), userInfo: nil, repeats: true)
// Do any additional setup after loading the view.
}
#objc func imageChange(){
self.imageView.image=images[i]
if i<images.count-1{
i+=1
}
else{
i=0
}
}
I have tried CollectionView for the carousel slideshow, but it didn't work out for me. I didn't like the hackish ways I had to do to make it show images in one row and I also didn't like the fact that it cannot return the active image (there is some workaround here as well, but they don't seem reliable). So, naturally, I ended up building a custom slideshow carousel for my purpose. I will share the code here, so hopefully, it can help(or at least guide someone) with a similar problem.
NOTE: My carousel is full width, singleImagePerScreen carousel, with a swipe recognizer to swipe through images and delegate function that is triggered when an image is active(I use it to display active image - "1 of 5").
TESTED ON: SWIFT 5, XCode 12.2, iOS 14.2
// ImageCarouselView class
import UIKit
class ImageCarouselView: UIView {
private let images: [UIImage?]
private var index = 0
private let screenWidth = UIScreen.main.bounds.width
var delegate: ImageCarouselViewDelegate?
lazy var previousImageView = imageView(image: nil, contentMode: .scaleAspectFit)
lazy var currentImageView = imageView(image: nil, contentMode: .scaleAspectFit)
lazy var nextImageView = imageView(image: nil, contentMode: .scaleAspectFit)
lazy var previousImageLeadingConstraint: NSLayoutConstraint = {
return previousImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: -screenWidth)
}()
lazy var currentImageLeadingConstraint: NSLayoutConstraint = {
return currentImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0)
}()
lazy var nextImageLeadingConstraint: NSLayoutConstraint = {
return nextImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: screenWidth)
}()
init(_ images: [UIImage?]) {
self.images = images
super.init(frame: .zero)
self.translatesAutoresizingMaskIntoConstraints = false
setupLayout()
setupImages()
setupSwipeRecognizer()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
private func setupLayout() {
self.subviews.forEach({ $0.removeFromSuperview() })
addSubview(previousImageView)
addSubview(currentImageView)
addSubview(nextImageView)
previousImageLeadingConstraint = previousImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: -screenWidth)
currentImageLeadingConstraint = currentImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0)
nextImageLeadingConstraint = nextImageView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: screenWidth)
NSLayoutConstraint.activate([
previousImageLeadingConstraint,
previousImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
previousImageView.widthAnchor.constraint(equalToConstant: screenWidth),
currentImageLeadingConstraint,
currentImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
currentImageView.widthAnchor.constraint(equalToConstant: screenWidth),
nextImageLeadingConstraint,
nextImageView.centerYAnchor.constraint(equalTo: centerYAnchor),
nextImageView.widthAnchor.constraint(equalToConstant: screenWidth),
])
}
private func setupImages() {
currentImageView.image = images[self.index]
guard images.count > 1 else { return }
if (index == 0) {
previousImageView.image = images[images.count - 1]
nextImageView.image = images[index + 1]
}
if (index == (images.count - 1)) {
previousImageView.image = images[index - 1]
nextImageView.image = images[0]
}
}
private func setupSwipeRecognizer() {
guard images.count > 1 else { return }
let leftSwipe = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipes))
let rightSwipe = UISwipeGestureRecognizer(target: self, action: #selector(handleSwipes))
leftSwipe.direction = .left
rightSwipe.direction = .right
self.addGestureRecognizer(leftSwipe)
self.addGestureRecognizer(rightSwipe)
}
#objc private func handleSwipes(_ sender: UISwipeGestureRecognizer) {
if (sender.direction == .left) {
showNextImage()
}
if (sender.direction == .right) {
showPreviousImage()
}
}
private func showPreviousImage() {
previousImageLeadingConstraint.constant = 0
currentImageLeadingConstraint.constant = screenWidth
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: {
self.layoutIfNeeded()
}, completion: { _ in
self.nextImageView = self.currentImageView
self.currentImageView = self.previousImageView
self.previousImageView = self.imageView(image: nil, contentMode: .scaleAspectFit)
self.index = self.index == 0 ? self.images.count - 1 : self.index - 1
self.delegate?.imageCarouselView(self, didShowImageAt: self.index)
self.previousImageView.image = self.index == 0 ? self.images[self.images.count - 1] : self.images[self.index - 1]
self.setupLayout()
})
}
private func showNextImage() {
nextImageLeadingConstraint.constant = 0
currentImageLeadingConstraint.constant = -screenWidth
UIView.animate(withDuration: 0.2, delay: 0.0, options: .curveEaseIn, animations: {
self.layoutIfNeeded()
}, completion: { _ in
self.previousImageView = self.currentImageView
self.currentImageView = self.nextImageView
self.nextImageView = self.imageView(image: nil, contentMode: .scaleAspectFit)
self.index = self.index == (self.images.count - 1) ? 0 : self.index + 1
self.delegate?.imageCarouselView(self, didShowImageAt: self.index)
self.nextImageView.image = self.index == (self.images.count - 1) ? self.images[0] : self.images[self.index + 1]
self.setupLayout()
})
}
func imageView(image: UIImage? = nil, contentMode: UIImageView.ContentMode) -> UIImageView {
let view = UIImageView()
view.image = image
view.contentMode = contentMode
view.translatesAutoresizingMaskIntoConstraints = false
return view
}
}
// ImageCarouselViewDelegate
import UIKit
protocol ImageCarouselViewDelegate: NSObjectProtocol {
func imageCarouselView(_ imageCarouselView: ImageCarouselView, didShowImageAt index: Int)
}
// Usage
let slideshowView = ImageCarouselView(images) // initialize
self.slideshowView.delegate = self // set delegate in viewDidLoad()
extension YourViewController: ImageCarouselViewDelegate {
func imageCarouselView(_ imageCarouselView: ImageCarouselView, didShowImageAt index: Int) {
// do something with index
}
}
You can add collection view, add image in your custom collectionview cell, after that do checked Paging Enabled on props panel for collectionview. Use timer for auto slide

Resources