Skip to content

Instantly share code, notes, and snippets.

@ahmedAlmasri
Created March 31, 2019 17:19
Show Gist options
  • Save ahmedAlmasri/b230033758a749f2cf72e94a676bae76 to your computer and use it in GitHub Desktop.
Save ahmedAlmasri/b230033758a749f2cf72e94a676bae76 to your computer and use it in GitHub Desktop.
import Foundation
import UIKit
func getWidth() -> CGFloat{
return UIScreen.main.bounds.width
}
func getHeight() -> CGFloat{
return UIScreen.main.bounds.height
}
public enum rotationWay {
case horizontal
case vertical
}
protocol SNPagerDelegate {
func currentPage(_ index:Int)
}
class SNPager: UIView{
var delegate:SNPagerDelegate?
private var _rotation: rotationWay!
var _count: Int!
/*
this count variable is added for binding between scrollViewDidScroll functions and limit of page.
If there have 3 page, SNPager has provide to scroll just between 0 and 3 section.
*/
var scrollView: UIScrollView!
var pageControl: UIPageControl!
// init function that represent SNPager with view
public init(frame: CGRect, viewArray uiviewArray:[UIView], _ rotation: rotationWay) {
// set the count before the init cause that otherwise return nil when detect scrolling
self._count = uiviewArray.count
super.init(frame: frame)
// set the rotation
self._rotation = rotation
let count:Int = uiviewArray.count
self._count = uiviewArray.count;
scrollView = UIScrollView()
scrollView.frame = CGRect(x: 0, y: 0, width: Int(UIScreen.main.bounds.width), height: Int(UIScreen.main.bounds.height))
scrollView.backgroundColor = UIColor.clear
scrollView.isPagingEnabled = true
// setting scroll view contentsize for given direction
switch rotation {
case .horizontal:
scrollView.contentSize = CGSize(width: Int(UIScreen.main.bounds.width)*count, height: 0)
scrollView.showsHorizontalScrollIndicator = false
case .vertical:
scrollView.contentSize = CGSize(width: 0, height: Int(UIScreen.main.bounds.height)*count)
scrollView.showsVerticalScrollIndicator = false
}
scrollView.delegate = self
// settings up pagecontrol
switch rotation {
case .vertical:
pageControl = UIPageControl(frame: CGRect(x: UIScreen.main.bounds.width-50-UIScreen.main.bounds.width/2 , y: 0, width: 50, height: 20))
pageControl.pageIndicatorTintColor = #colorLiteral(red: 0.9254901961, green: 0.6862745098, blue: 0.1411764706, alpha: 0.5184033891)
pageControl.currentPageIndicatorTintColor = #colorLiteral(red: 0.9254901961, green: 0.6862745098, blue: 0.1411764706, alpha: 1)
pageControl.transform = pageControl.transform.rotated(by: .pi/2)
pageControl.center.y = scrollView.center.y
case .horizontal:
pageControl = UIPageControl(frame: CGRect(x: 0, y:self.frame.height-35, width: 100, height: 20))
pageControl.pageIndicatorTintColor = #colorLiteral(red: 0.9254901961, green: 0.6862745098, blue: 0.1411764706, alpha: 0.5184033891)
pageControl.currentPageIndicatorTintColor = #colorLiteral(red: 0.9254901961, green: 0.6862745098, blue: 0.1411764706, alpha: 1)
pageControl.center.x = self.center.x
}
self.attributesForPageControl(pageControl,count)
self.addSubview(pageControl)
var viewArray: [UIView?] = [UIView?].init(repeating: nil, count: count)
// initialize and setting up frame the uiviews with every view of viewArray
for i in 0...count-1 {
viewArray[i] = UIView()
switch rotation{
case .horizontal:
viewArray[i]?.frame = CGRect(x: pageToFloatHorizontal(i), y: 0, width: getWidth(), height: getHeight())
uiviewArray[i].frame.origin = CGPoint(x: pageToFloatHorizontal(i), y: 0)
case .vertical:
viewArray[i]?.frame = CGRect(x: 0, y: pageToFloatVertical(i), width: getWidth(), height: getHeight())
uiviewArray[i].frame.origin = CGPoint(x: 0, y: pageToFloatVertical(i))
}
viewArray[i]! = uiviewArray[i]
scrollView.addSubview(viewArray[i]!)
}
self.addSubview(scrollView)
switch rotation {
case .vertical:
scrollView.setContentOffset(CGPoint.init(x: 0, y: 20), animated: false)
scrollView.setContentOffset(CGPoint.init(x: 0, y: 0), animated: false)
default:
break
}
}
// init function that represent SNPager with images
public init(frame: CGRect, imageArray uiimageArray:[UIImage],_ rotation: rotationWay ){
self._count = uiimageArray.count;
super.init(frame: frame)
self._rotation = rotation
let count:Int = uiimageArray.count
scrollView = UIScrollView()
scrollView.frame = CGRect(x: 0, y: 0, width: Int(UIScreen.main.bounds.width), height: Int(UIScreen.main.bounds.height))
scrollView.backgroundColor = UIColor.clear
scrollView.isPagingEnabled = true
// setting scroll view contentsize for given direction
switch rotation {
case .horizontal:
scrollView.contentSize = CGSize(width: Int(UIScreen.main.bounds.width)*count, height: 0)
scrollView.showsHorizontalScrollIndicator = false
case .vertical:
scrollView.contentSize = CGSize(width: 0, height: Int(UIScreen.main.bounds.height)*count)
scrollView.showsVerticalScrollIndicator = false
}
scrollView.delegate = self
// settings up pagecontrol
switch rotation {
case .vertical:
pageControl = UIPageControl(frame: CGRect(x: UIScreen.main.bounds.width-50-UIScreen.main.bounds.width/2 , y: 0, width: 50, height: 20))
// transform the pageControl for vertical position
pageControl.transform = pageControl.transform.rotated(by: .pi/2)
pageControl.center.y = scrollView.center.y
case .horizontal:
pageControl = UIPageControl(frame: CGRect(x: 0, y: UIScreen.main.bounds.height-50, width: 100, height: 20))
pageControl.center.x = self.center.x
}
self.attributesForPageControl(pageControl,count)
self.addSubview(pageControl)
var imageViewArray: [UIImageView?] = [UIImageView?].init(repeating: nil, count: count)
// initialize and setting up frame the uiviews with every view of viewArray
for i in 0...count-1 {
imageViewArray[i] = UIImageView()
switch rotation{
case .horizontal:
imageViewArray[i]?.frame = CGRect(x: pageToFloatHorizontal(i), y: 0, width: getWidth(), height: getHeight())
case .vertical:
imageViewArray[i]?.frame = CGRect(x: 0, y: pageToFloatVertical(i), width: getWidth(), height: getHeight())
}
imageViewArray[i]?.image = (uiimageArray[i])
scrollView.addSubview(imageViewArray[i]!)
}
self.addSubview(scrollView)
switch rotation {
case .vertical:
scrollView.setContentOffset(CGPoint.init(x: 0, y: 20), animated: false)
scrollView.setContentOffset(CGPoint.init(x: 0, y: 0), animated: false)
default:
break
}
}
// helper methods
func scrollToPage(page: Int, animated: Bool) {
var frame: CGRect = self.scrollView.frame
// frame.origin.x =
frame.origin.y = 0
//self.scrollView.scrollRectToVisible(frame, animated: animated)
scrollView.setContentOffset(CGPoint(x: frame.size.width * CGFloat(page), y: 0), animated: true)
}
private func attributesForPageControl(_ pageControl: UIPageControl, _ count:Int){
pageControl.numberOfPages = count
pageControl.currentPage = 0
pageControl.layer.zPosition = 1
pageControl.backgroundColor = UIColor.clear
}
fileprivate func pageToFloatVertical(_ simpleInteger: Int) -> CGFloat{
return CGFloat(simpleInteger) * UIScreen.main.bounds.height
}
fileprivate func pageToFloatHorizontal(_ simpleInteger: Int) -> CGFloat{
return CGFloat(simpleInteger) * UIScreen.main.bounds.width
}
fileprivate func offsetToPage(_ scrollViewOffset: CGFloat) -> Int{
return Int(scrollViewOffset / UIScreen.main.bounds.width)
}
fileprivate func offsetToPageVertical(withHeightOffset scrollViewOffset: CGFloat) -> Int{
return Int(scrollViewOffset / UIScreen.main.bounds.height)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
}
extension SNPager: UIScrollViewDelegate{
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// its forbidden to scroll to negative offset or upper offset of biggest offset limit.
let rotation: rotationWay = _rotation!
let count: Int = _count!
switch rotation {
case .horizontal:
if scrollView.contentOffset.x <= 0{
scrollView.setContentOffset(CGPoint.init(x: 0, y: 0), animated: false)
}else if scrollView.contentOffset.x >= UIScreen.main.bounds.width*CGFloat(count-1){
scrollView.setContentOffset(CGPoint.init(x: Int(UIScreen.main.bounds.width)*(count-1), y: 0), animated: false)
}
case .vertical:
if scrollView.contentOffset.y <= 0{
scrollView.setContentOffset(CGPoint.init(x: 0, y: 0), animated: false)
}else if scrollView.contentOffset.y >= UIScreen.main.bounds.height*CGFloat(count-1){
scrollView.setContentOffset(CGPoint.init(x: 0, y: Int(UIScreen.main.bounds.height)*(count-1)), animated: false)
}
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
// setting pageControl currentPage with every changing on scrollView page.
let rotation: rotationWay = _rotation!
switch rotation {
case .horizontal:
pageControl.currentPage = offsetToPage(scrollView.contentOffset.x)
case .vertical:
pageControl.currentPage = offsetToPageVertical(withHeightOffset: scrollView.contentOffset.y)
}
delegate?.currentPage(pageControl.currentPage)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment