Skip to content

Commit 6c19bf5

Browse files
nunoonunchili-ios
authored andcommitted
Added support to Multiple Tint Colors (#35)
* Added an array of tintColors for the layer's backgrounds on the BasePageControl * Added support of the TintColors on the different PageControls * Updated README to show the usage of multiple tint colors * Added an example of how to add the colored page control
1 parent fcb3cff commit 6c19bf5

13 files changed

+192
-38
lines changed

CHIPageControl/CHIPageControlAji.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ open class CHIPageControlAji: CHIBasePageControl {
6868
active.backgroundColor = (self.currentPageTintColor ?? self.tintColor)?.cgColor
6969
active.frame = frame
7070

71-
inactive.forEach() { layer in
72-
layer.backgroundColor = self.tintColor.withAlphaComponent(self.inactiveTransparency).cgColor
71+
inactive.enumerated().forEach() { index, layer in
72+
layer.backgroundColor = self.tintColor(position: index).withAlphaComponent(self.inactiveTransparency).cgColor
7373
if self.borderWidth > 0 {
7474
layer.borderWidth = self.borderWidth
75-
layer.borderColor = self.tintColor.cgColor
75+
layer.borderColor = self.tintColor(position: index).cgColor
7676
}
7777
layer.cornerRadius = self.radius
7878
layer.frame = frame

CHIPageControl/CHIPageControlAleppo.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -87,11 +87,11 @@ open class CHIPageControlAleppo: CHIBasePageControl {
8787
active.backgroundColor = (self.currentPageTintColor ?? self.tintColor)?.cgColor
8888
active.frame = frame
8989

90-
inactive.forEach() { layer in
91-
layer.backgroundColor = self.tintColor.withAlphaComponent(self.inactiveTransparency).cgColor
90+
inactive.enumerated().forEach() { index, layer in
91+
layer.backgroundColor = self.tintColor(position: index).withAlphaComponent(self.inactiveTransparency).cgColor
9292
if self.borderWidth > 0 {
9393
layer.borderWidth = self.borderWidth
94-
layer.borderColor = self.tintColor.cgColor
94+
layer.borderColor = self.tintColor(position: index).cgColor
9595
}
9696
layer.cornerRadius = self.radius
9797
layer.frame = frame

CHIPageControl/CHIPageControlChimayo.swift

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,11 +67,11 @@ open class CHIPageControlChimayo: CHIBasePageControl {
6767
let y = (self.bounds.size.height - self.diameter)*0.5
6868
var frame = CGRect(x: x, y: y, width: self.diameter, height: self.diameter)
6969

70-
inactive.forEach() { layer in
70+
inactive.enumerated().forEach() { index, layer in
7171
layer.cornerRadius = self.radius
7272
layer.frame = frame
7373
frame.origin.x += self.diameter + self.padding
74-
layer.backgroundColor = self.tintColor.cgColor
74+
layer.backgroundColor = self.tintColor(position: index).cgColor
7575
}
7676
update(for: progress)
7777
}

CHIPageControl/CHIPageControlFresno.swift

+7-4
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ open class CHIPageControlFresno: CHIBasePageControl {
6666
let y = (self.bounds.size.height - self.diameter)*0.5
6767
var frame = CGRect(x: x, y: y, width: self.diameter, height: self.diameter)
6868

69-
elements.forEach() { layer in
70-
layer.backgroundColor = self.tintColor.withAlphaComponent(self.inactiveTransparency).cgColor
69+
elements.enumerated().forEach() { index, layer in
70+
layer.backgroundColor = self.tintColor(position: index).withAlphaComponent(self.inactiveTransparency).cgColor
7171
if self.borderWidth > 0 {
7272
layer.borderWidth = self.borderWidth
73-
layer.borderColor = self.tintColor.cgColor
73+
layer.borderColor = self.tintColor(position: index).cgColor
7474
}
7575
layer.cornerRadius = self.radius
7676
layer.frame = frame
@@ -127,12 +127,14 @@ open class CHIPageControlFresno: CHIBasePageControl {
127127
guard frames.indices.contains(index - 1), frames.indices.contains(index) else { return }
128128

129129
let prev = frames[index - 1]
130+
let prevColor = tintColor(position: index - 1)
130131
let current = frames[index]
132+
let currentColor = tintColor(position: index)
131133

132134
let elementTotal: CGFloat = current.origin.x - prev.origin.x
133135
let elementProgress: CGFloat = current.origin.x - active.frame.origin.x
134136
let elementPercent = (elementTotal - elementProgress) / elementTotal
135-
137+
136138
// x: input, a: input min, b: input max, c: output min, d: output max
137139
// returns mapped value x from (a,b) to (c, d)
138140
let linearTransform = { (x: CGFloat, a: CGFloat, b: CGFloat, c: CGFloat, d: CGFloat) -> CGFloat in
@@ -141,6 +143,7 @@ open class CHIPageControlFresno: CHIBasePageControl {
141143

142144
element.frame = prev
143145
element.frame.origin.x = linearTransform(elementPercent, 1.0, 0.0, prev.origin.x, current.origin.x)
146+
element.backgroundColor = blend(color1: currentColor, color2: prevColor, progress: elementPercent).withAlphaComponent(self.inactiveTransparency).cgColor
144147

145148
if elementPercent <= 0.5 {
146149
let originY = linearTransform(elementPercent, 0.0, 0.5, 0, self.radius + self.padding)

CHIPageControl/CHIPageControlJalapeno.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,11 @@ open class CHIPageControlJalapeno: CHIBasePageControl {
129129
let y = (self.bounds.size.height - self.diameter)*0.5
130130
var frame = CGRect(x: x, y: y, width: self.diameter, height: self.diameter)
131131

132-
inactive.forEach() { layer in
133-
layer.backgroundColor = self.tintColor.withAlphaComponent(self.inactiveTransparency).cgColor
132+
inactive.enumerated().forEach() { index, layer in
133+
layer.backgroundColor = self.tintColor(position: index).withAlphaComponent(self.inactiveTransparency).cgColor
134134
if self.borderWidth > 0 {
135135
layer.borderWidth = self.borderWidth
136-
layer.borderColor = self.tintColor.cgColor
136+
layer.borderColor = self.tintColor(position: index).cgColor
137137
}
138138
layer.cornerRadius = self.radius
139139
layer.frame = frame

CHIPageControl/CHIPageControlJaloro.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,11 @@ open class CHIPageControlJaloro: CHIBasePageControl {
7777
active.backgroundColor = (self.currentPageTintColor ?? self.tintColor)?.cgColor
7878
active.frame = frame
7979

80-
inactive.forEach() { layer in
81-
layer.backgroundColor = self.tintColor.withAlphaComponent(self.inactiveTransparency).cgColor
80+
inactive.enumerated().forEach() { index, layer in
81+
layer.backgroundColor = self.tintColor(position: index).withAlphaComponent(self.inactiveTransparency).cgColor
8282
if self.borderWidth > 0 {
8383
layer.borderWidth = self.borderWidth
84-
layer.borderColor = self.tintColor.cgColor
84+
layer.borderColor = self.tintColor(position: index).cgColor
8585
}
8686
layer.cornerRadius = self.radius
8787
layer.frame = frame

CHIPageControl/CHIPageControlPaprika.swift

+12-4
Original file line numberDiff line numberDiff line change
@@ -68,11 +68,11 @@ open class CHIPageControlPaprika: CHIBasePageControl {
6868
let y = (self.bounds.size.height - self.diameter)*0.5
6969
var frame = CGRect(x: x, y: y, width: self.diameter, height: self.diameter)
7070

71-
elements.forEach() { layer in
72-
layer.backgroundColor = self.tintColor.withAlphaComponent(self.inactiveTransparency).cgColor
71+
elements.enumerated().forEach() { index, layer in
72+
layer.backgroundColor = self.tintColor(position: index).withAlphaComponent(self.inactiveTransparency).cgColor
7373
if self.borderWidth > 0 {
7474
layer.borderWidth = self.borderWidth
75-
layer.borderColor = self.tintColor.cgColor
75+
layer.borderColor = self.tintColor(position: index).cgColor
7676
}
7777
layer.cornerRadius = self.radius
7878
layer.frame = frame
@@ -139,9 +139,17 @@ open class CHIPageControlPaprika: CHIBasePageControl {
139139
guard frames.indices.contains(page), frames.indices.contains(page + 1) else { return }
140140

141141
let prev = frames[page]
142+
let prevColor = tintColor(position: page)
142143
let current = frames[page + 1]
144+
let currentColor = tintColor(position: page + 1)
145+
146+
let elementTotal: CGFloat = current.origin.x - prev.origin.x
147+
let elementProgress: CGFloat = current.origin.x - active.frame.origin.x
148+
let elementPercent = (elementTotal - elementProgress) / elementTotal
149+
150+
element.borderColor = blend(color1: currentColor, color2: prevColor, progress: elementPercent).cgColor
143151
element.frame = prev
144-
element.frame.origin.x += current.origin.x - active.frame.origin.x
152+
element.frame.origin.x += elementProgress
145153
element.frame.origin.y = 2*min.origin.y - active.frame.origin.y
146154
}
147155

CHIPageControl/CHIPageControlPuya.swift

+12-4
Original file line numberDiff line numberDiff line change
@@ -66,11 +66,11 @@ open class CHIPageControlPuya: CHIBasePageControl {
6666
let y = (self.bounds.size.height - self.diameter)*0.5
6767
var frame = CGRect(x: x, y: y, width: self.diameter, height: self.diameter)
6868

69-
elements.forEach() { layer in
70-
layer.backgroundColor = self.tintColor.withAlphaComponent(self.inactiveTransparency).cgColor
69+
elements.enumerated().forEach() { index, layer in
70+
layer.backgroundColor = self.tintColor(position: index).withAlphaComponent(self.inactiveTransparency).cgColor
7171
if self.borderWidth > 0 {
7272
layer.borderWidth = self.borderWidth
73-
layer.borderColor = self.tintColor.cgColor
73+
layer.borderColor = self.tintColor(position: index).cgColor
7474
}
7575
layer.cornerRadius = self.radius
7676
layer.frame = frame
@@ -121,9 +121,17 @@ open class CHIPageControlPuya: CHIBasePageControl {
121121
guard frames.indices.contains(page), frames.indices.contains(page + 1) else { return }
122122

123123
let prev = frames[page]
124+
let prevColor = tintColor(position: page)
124125
let current = frames[page + 1]
126+
let currentColor = tintColor(position: page + 1)
127+
128+
let elementTotal: CGFloat = current.origin.x - prev.origin.x
129+
let elementProgress: CGFloat = current.origin.x - active.frame.origin.x
130+
let elementPercent = (elementTotal - elementProgress) / elementTotal
131+
132+
element.backgroundColor = blend(color1: currentColor, color2: prevColor, progress: elementPercent).withAlphaComponent(self.inactiveTransparency).cgColor
125133
element.frame = prev
126-
element.frame.origin.x += current.origin.x - active.frame.origin.x
134+
element.frame.origin.x += elementProgress
127135
}
128136

129137
override open var intrinsicContentSize: CGSize {

CHIPageControl/Core/CHIBasePageControl.swift

+53
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import UIKit
2929

3030
@IBInspectable open var numberOfPages: Int = 0 {
3131
didSet {
32+
populateTintColors()
3233
updateNumberOfPages(numberOfPages)
3334
self.isHidden = hidesForSinglePage && numberOfPages <= 1
3435
}
@@ -83,6 +84,15 @@ import UIKit
8384
setNeedsLayout()
8485
}
8586
}
87+
88+
open var tintColors: [UIColor] = [] {
89+
didSet {
90+
guard tintColors.count == numberOfPages else {
91+
fatalError("The number of tint colors needs to be the same as the number of page")
92+
}
93+
setNeedsLayout()
94+
}
95+
}
8696

8797
@IBInspectable open var currentPageTintColor: UIColor? {
8898
didSet {
@@ -122,6 +132,35 @@ import UIKit
122132
}
123133
}
124134

135+
func tintColor(position: Int) -> UIColor {
136+
if tintColors.count < numberOfPages {
137+
return tintColor
138+
} else {
139+
return tintColors[position]
140+
}
141+
}
142+
143+
open func insertTintColor(_ color: UIColor, position: Int) {
144+
if tintColors.count < numberOfPages {
145+
setupTintColors()
146+
}
147+
tintColors[position] = color
148+
}
149+
150+
private func setupTintColors() {
151+
tintColors = Array<UIColor>(repeating: tintColor, count: numberOfPages)
152+
}
153+
154+
private func populateTintColors() {
155+
guard tintColors.count > 0 else { return }
156+
157+
if tintColors.count > numberOfPages {
158+
tintColors = Array(tintColors.prefix(numberOfPages))
159+
} else if tintColors.count < numberOfPages {
160+
tintColors.append(contentsOf: Array<UIColor>(repeating: tintColor, count: numberOfPages - tintColors.count))
161+
}
162+
}
163+
125164
func animate() {
126165
guard let moveToProgress = self.moveToProgress else { return }
127166

@@ -159,3 +198,17 @@ import UIKit
159198
fatalError("Should be implemented in child class")
160199
}
161200
}
201+
202+
extension CHIBasePageControl {
203+
internal func blend(color1: UIColor, color2: UIColor, progress: CGFloat) -> UIColor {
204+
let l1 = 1 - progress
205+
let l2 = progress
206+
var (r1, g1, b1, a1): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
207+
var (r2, g2, b2, a2): (CGFloat, CGFloat, CGFloat, CGFloat) = (0, 0, 0, 0)
208+
209+
color1.getRed(&r1, green: &g1, blue: &b1, alpha: &a1)
210+
color2.getRed(&r2, green: &g2, blue: &b2, alpha: &a2)
211+
212+
return UIColor(red: l1*r1 + l2*r2, green: l1*g1 + l2*g2, blue: l1*b1 + l2*b2, alpha: l1*a1 + l2*a2)
213+
}
214+
}

Example/Example/Assets.xcassets/AppIcon.appiconset/Contents.json

+15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,15 @@
11
{
22
"images" : [
3+
{
4+
"idiom" : "iphone",
5+
"size" : "20x20",
6+
"scale" : "2x"
7+
},
8+
{
9+
"idiom" : "iphone",
10+
"size" : "20x20",
11+
"scale" : "3x"
12+
},
313
{
414
"idiom" : "iphone",
515
"size" : "29x29",
@@ -29,6 +39,11 @@
2939
"idiom" : "iphone",
3040
"size" : "60x60",
3141
"scale" : "3x"
42+
},
43+
{
44+
"idiom" : "ios-marketing",
45+
"size" : "1024x1024",
46+
"scale" : "1x"
3247
}
3348
],
3449
"info" : {

0 commit comments

Comments
 (0)