Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions Example/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,37 @@ class ViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var pageControl: ISPageControl!
var pageControl1: ISPageControl!
var pageControl2: ISPageControl!
let images: [UIImage] = [#imageLiteral(resourceName: "bg1"), #imageLiteral(resourceName: "bg2"), #imageLiteral(resourceName: "bg3"), #imageLiteral(resourceName: "bg4"), #imageLiteral(resourceName: "bg5"), #imageLiteral(resourceName: "bg6"), #imageLiteral(resourceName: "bg7"), #imageLiteral(resourceName: "bg8")]

override func viewDidLoad() {
super.viewDidLoad()
pageControl.numberOfPages = images.count

let frame = CGRect(x: 0, y: 500, width: UIScreen.main.bounds.width, height: 100)
pageControl1 = ISPageControl(frame: frame, numberOfPages: images.count)
pageControl1.radius = 8
let frame1 = CGRect(x: 0, y: 450, width: UIScreen.main.bounds.width, height: 100)
pageControl1 = ISPageControl(frame: frame1, numberOfPages: images.count)
pageControl1.dotRadius = 8
pageControl1.padding = 10
pageControl1.inactiveTintColor = UIColor.white.withAlphaComponent(0.4)
pageControl1.currentPageTintColor = UIColor.black
pageControl1.borderWidth = 1
pageControl1.borderColor = UIColor.black.withAlphaComponent(0.4)
view.addSubview(pageControl1)

let frame2 = CGRect(x: 0, y: 550, width: UIScreen.main.bounds.width, height: 100)
pageControl2 = ISPageControl(frame: frame2, numberOfPages: images.count)
pageControl2.dotRadius = 3
pageControl2.dotHeight = 6
pageControl2.dotWidth = 30
pageControl2.minOpacityValue = 0.2
pageControl2.middleOpacityValue = 0.6
pageControl2.fadeOpacity = true
pageControl2.fadeScale = false
pageControl2.inactiveTintColor = UIColor.white.withAlphaComponent(0.4)
pageControl2.currentPageTintColor = UIColor.black
pageControl2.borderWidth = 1
pageControl2.borderColor = UIColor.black.withAlphaComponent(0.4)
view.addSubview(pageControl2)
}
}

Expand Down Expand Up @@ -58,6 +74,7 @@ extension ViewController: UIScrollViewDelegate {
let pageNumber = round(scrollView.contentOffset.x / scrollView.frame.size.width)
pageControl.currentPage = Int(pageNumber)
pageControl1.currentPage = Int(pageNumber)
pageControl2.currentPage = Int(pageNumber)
}
}

Expand Down
112 changes: 92 additions & 20 deletions Sources/ISPageControl.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,22 @@
import UIKit

open class ISPageControl: UIControl {

open var fadeScale: Bool = true {
didSet {
setNeedsLayout()
}
}

open var fadeOpacity: Bool = false {
didSet {
setNeedsLayout()
}
}

fileprivate let limit = 5
fileprivate var fullScaleIndex = [0, 1, 2]
fileprivate var dotLayers: [CALayer] = []
fileprivate var diameter: CGFloat { return radius * 2 }
fileprivate var centerIndex: Int { return fullScaleIndex[1] }

open var currentPage = 0 {
Expand All @@ -36,8 +48,32 @@ open class ISPageControl: UIControl {
}
}

@IBInspectable open var radius: CGFloat = 5 {
@IBInspectable open var dotRadius: CGFloat = 5 {
didSet {
if dotHeight < 2 * dotRadius {
dotHeight = 2 * dotRadius
}
if dotWidth < 2 * dotRadius {
dotWidth = 2 * dotRadius
}
updateDotLayersLayout()
}
}

@IBInspectable open var dotWidth: CGFloat = 10 {
didSet {
if dotRadius > dotWidth / 2 {
dotRadius = dotWidth / 2
}
updateDotLayersLayout()
}
}

@IBInspectable open var dotHeight: CGFloat = 10 {
didSet {
if dotRadius > dotHeight / 2 {
dotRadius = dotHeight / 2
}
updateDotLayersLayout()
}
}
Expand All @@ -60,6 +96,18 @@ open class ISPageControl: UIControl {
}
}

@IBInspectable open var minOpacityValue: CGFloat = 0.4 {
didSet {
setNeedsLayout()
}
}

@IBInspectable open var middleOpacityValue: CGFloat = 0.7 {
didSet {
setNeedsLayout()
}
}

@IBInspectable open var numberOfPages: Int = 0 {
didSet {
setupDotLayers()
Expand Down Expand Up @@ -107,7 +155,7 @@ open class ISPageControl: UIControl {

override open func sizeThatFits(_ size: CGSize) -> CGSize {
let minValue = min(7, numberOfPages)
return CGSize(width: CGFloat(minValue) * diameter + CGFloat(minValue - 1) * padding, height: diameter)
return CGSize(width: CGFloat(minValue) * dotWidth + CGFloat(minValue - 1) * padding, height: dotHeight)
}

open override func layoutSubviews() {
Expand Down Expand Up @@ -143,14 +191,14 @@ private extension ISPageControl {

func updateDotLayersLayout() {
let floatCount = CGFloat(numberOfPages)
let x = (bounds.size.width - diameter * floatCount - padding * (floatCount - 1)) * 0.5
let y = (bounds.size.height - diameter) * 0.5
var frame = CGRect(x: x, y: y, width: diameter, height: diameter)
let x = (bounds.size.width - dotWidth * floatCount - padding * (floatCount - 1)) * 0.5
let y = (bounds.size.height - dotHeight) * 0.5
var frame = CGRect(x: x, y: y, width: dotWidth, height: dotHeight)

dotLayers.forEach {
$0.cornerRadius = radius
$0.cornerRadius = dotRadius
$0.frame = frame
frame.origin.x += diameter + padding
frame.origin.x += dotWidth + padding
}
}

Expand All @@ -160,7 +208,7 @@ private extension ISPageControl {

dotLayers.enumerated().filter{ $0.offset != centerIndex }.forEach {
let index = abs($0.offset - centerIndex)
let interval = $0.offset > centerIndex ? diameter + padding : -(diameter + padding)
let interval = $0.offset > centerIndex ? dotWidth + padding : -(dotWidth + padding)
$0.element.position = CGPoint(x: centerLayer.position.x + interval * CGFloat(index), y: $0.element.position.y)
}
}
Expand All @@ -171,20 +219,44 @@ private extension ISPageControl {
return
}

var transform = CGAffineTransform.identity
if !fullScaleIndex.contains($0.offset) {
var scaleValue: CGFloat = 0
if abs($0.offset - first) == 1 || abs($0.offset - last) == 1 {
scaleValue = min(middleScaleValue, 1)
} else if abs($0.offset - first) == 2 || abs($0.offset - last) == 2 {
scaleValue = min(minScaleValue, 1)
} else {
scaleValue = 0
if fadeScale {

var transform = CGAffineTransform.identity
if !fullScaleIndex.contains($0.offset) {
var scaleValue: CGFloat = 0
if abs($0.offset - first) == 1 || abs($0.offset - last) == 1 {
scaleValue = min(middleScaleValue, 1)
} else if abs($0.offset - first) == 2 || abs($0.offset - last) == 2 {
scaleValue = min(minScaleValue, 1)
} else {
scaleValue = 0
}
transform = transform.scaledBy(x: scaleValue, y: scaleValue)
}

$0.element.setAffineTransform(transform)
}

if fadeOpacity {

var opacity: CGFloat = 1
if !fullScaleIndex.contains($0.offset) {
var scaleValue: CGFloat = 0
if abs($0.offset - first) == 1 || abs($0.offset - last) == 1 {
scaleValue = min(middleOpacityValue, 1)
} else if abs($0.offset - first) == 2 || abs($0.offset - last) == 2 {
scaleValue = min(minOpacityValue, 1)
} else {
scaleValue = 0
}
opacity = scaleValue
}
transform = transform.scaledBy(x: scaleValue, y: scaleValue)

$0.element.opacity = Float(opacity)

}

$0.element.setAffineTransform(transform)

}
}

Expand Down