Skip to content

Commit bc5abc2

Browse files
author
Xavier Schott
committed
Swift 3
2 parents 3d7040a + 08a39f6 commit bc5abc2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

55 files changed

+1676
-3822
lines changed
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
Copyright (c) 2014 Xavier Schott
1+
Copyright (c) 2017 Xavier Schott
22

33
Permission is hereby granted, free of charge, to any person obtaining a copy
44
of this software and associated documentation files (the "Software"), to deal
@@ -16,4 +16,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
1616
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
1717
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
1818
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19-
THE SOFTWARE.
19+
THE SOFTWARE.

README.md

Lines changed: 69 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
# Slider with _ticks_ + animated Label
2-
TGPControls are drop-in replacement of `UISlider` & `UILabel`, with visual preview in **Interface Builder**.
1+
# Slider with _ticks_ & animated Label (Swift)
2+
TGPControls are drop-in replacement of `UISlider` & `UILabel`, with visual preview in **Interface Builder**, single liner instrumentation, smooth animations, simple API, powerful customization.
33

44
## What's DiscreteSlider?
55
![ticksdemo](https://cloud.githubusercontent.com/assets/4073988/5912371/144aaf24-a588-11e4-9a22-42832eb2c235.gif)
66

7-
`TGPDiscreteSlider`: A slider with discrete steps, discrete range, with customizable track, thumb and ticks.
8-
Ideal to select steps.
7+
`TGPDiscreteSlider`: A slider with discrete steps (i.e. ticks), discrete range, with customizable track, thumb and ticks.
8+
Ideal to select individual steps, star rating, integers, rainbow colors, slices and in general any value that is not a continuum. Just set the number of stops, TGPDiscreteSlider handles the selection and the animations for you.
99

1010
## What's CamelLabels?
1111
![camellabels2](https://cloud.githubusercontent.com/assets/4073988/5912454/15774398-a589-11e4-8f08-18c9c7b59871.gif)
1212

13-
`TGPCamelLabels`: A set of animated labels representing a selection. Can be used alone or in conjunction with a UIControl.
13+
`TGPCamelLabels`: A set of animated labels (dock effect) representing a selection. Can be used alone or in conjunction with a UIControl.
1414
Ideal to represent steps. *The discrete slider and the camel labels can work in unison.*
1515

1616
## Compatibility
17-
1. Can be integrated with **Swift** or **Obj-C**
18-
2. `TGPControls` are **AutoLayout** ready, support **iOS 9 & iOS 8** `IB Designable` and `IB Inspectable` properties, yet runs as far back as **iOS 7**
19-
3. Comes with two demo applications, one in **Swift** and one in **Objective-C**
17+
1. Written in **Swift 3**, can be integrated with **Swift** or **Obj-C**
18+
2. `TGPControls` are **AutoLayout**, `IB Designable` and `IB Inspectable` ready (†)
19+
3. Version 3.0.0 comes with a **Swift 3** demo application, for **iOS 10** down to **8**.
20+
(†) Earlier 2.x versions provide **iOS 7** support
2021

2122
![imagessliderdemo](https://cloud.githubusercontent.com/assets/4073988/6628373/183c7452-c8c2-11e4-9a63-107805bc0cc4.gif)
2223

@@ -42,43 +43,47 @@ Most customization can be done in **Interface Builder** and require **zero codin
4243

4344
## How to integrate
4445
Using [CocoaPods](http://cocoapods.org/?q=TGPControls)
45-
- **iOS 9 and later, iOS 8**: install CocoaPods 0.36.0+ [CocoaPods-Frameworks](http://blog.cocoapods.org/Pod-Authors-Guide-to-CocoaPods-Frameworks/), add `use_frameworks!` to your podfile.
46-
- **iOS 7**: restrict yourself to `TGPCamelLabels7.{h,m}` and `TGPDiscreteSlider7.{h,m}`. Compatible with CocoaPods 0.35.0.
47-
*Note: When integrating into an iOS 7 project, use the TGPCamelLabels7 and TGPDiscreteSlider7 classes in Interface Builder.*
46+
- **iOS 10 and later down to iOS 8**: install CocoaPods 1.2.0+ [CocoaPods-Frameworks](http://blog.cocoapods.org/Pod-Authors-Guide-to-CocoaPods-Frameworks/), add `use_frameworks!` to your podfile.
47+
- **iOS 7**: Use TGPControls version 2.1.0
4848

4949
Besides customization, which you can do entirely under Interface Builder in iOS 8 and later, both `TGPDiscreteSlider` and `TGPCamelLabels` require surprisingly little code to integrate.
5050

51-
### TGPDiscreteSlider
51+
### DiscreteSlider
5252

5353
For simplicity, TGPDiscreteSlider does *not* descend from UISlider but from **UIControl**.
5454
It uses a `minimumValue`, a `tickCount` and an `incrementValue` (instead of *minimumValue* and *maximumValue*).
55-
All graphic aspects, such as physical spacing of the ticks or physical width of the track are controlled internally.
56-
This makes TGPDiscreteSlider predictable. it is guaranteed to always fit snuggly inside its bounds.
55+
All graphic aspects, such as physical spacing of the ticks or physical width of the track are controlled internally. This makes TGPDiscreteSlider predictable. it is guaranteed to always fit snuggly inside its bounds.
5756

58-
**Step 1**: *register* to notifications (*just like any UIControl*)
57+
**Single step**: To use DiscreteSlider + CamelLabels in tandem, you need exactly **1 line of code**:
5958
```
60-
[self.discreteSlider addTarget:self
61-
action:@selector(discreteSliderValueChanged:)
62-
forControlEvents:UIControlEventValueChanged];
59+
discreteSlider.ticksListener = camelLabels
6360
```
64-
**Step 2**: *respond* to notification
61+
![complete](https://cloud.githubusercontent.com/assets/4073988/5912616/26cf1b0a-a58b-11e4-92f7-f9dbcd53c413.gif)
62+
That's all!
63+
Through the `TGPControlsTicksProtocol`, the camelLabels listen to _value_ and _size_ changes. You may want to adopt this protocol to handle changes, or use the traditional `UIControl` notifications:
64+
65+
**Advanced Steps (1a)**: *register* to notifications (*just like any UIControl*)
66+
```
67+
discreteSlider.addTarget(self,
68+
action: #selector(valueChanged(_:event:)),
69+
for: .valueChanged)
70+
```
71+
**Advanced Steps (1b)**: *respond* to notification
6572
```
66-
- (IBAction)discreteSliderValueChanged:(TGPDiscreteSlider *)sender {
67-
[self.camelLabels setValue:sender.value];
73+
func valueChanged(_ sender: TGPDiscreteSlider, event:UIEvent) {
74+
self.stepper.value = Double(sender.value)
6875
}
6976
```
70-
The above 6 lines of code are **all you need** to create this control:
7177

72-
![complete](https://cloud.githubusercontent.com/assets/4073988/5912616/26cf1b0a-a58b-11e4-92f7-f9dbcd53c413.gif)
7378

7479
**tickStyle, trackStyle, thumbStyle Properties:**
7580

7681
| Constant | Value | |
7782
|:--------------|:------------:| ----- |
78-
| `ComponentStyleIOS` | 0 | Gives to any component the iOS appearance: Ticks are invisible, track is blue and gray, thumb is round with a shadow |
79-
| `ComponentStyleRectangular` | 1 | Boxy look with hard edges |
80-
| `ComponentStyleRounded` | 2 | From rounded rectangles to perfects circles, depending on vertical to horizontal ratio |
81-
| `ComponentStyleInvisible` | 3 | Surprisingly useful to individually hide ticks, track, or even thumb |
83+
| `.iOS` | 0 | Gives to any component the iOS appearance: Ticks are invisible, track is blue and gray, thumb is round with a shadow |
84+
| `.rectangular` | 1 | Boxy look with hard edges |
85+
| `.rounded` | 2 | From rounded rectangles to perfects circles, depending on vertical to horizontal ratio |
86+
| `.invisible` | 3 | Surprisingly useful to individually hide ticks, track, or even thumb |
8287

8388
**Other Properties:**
8489

@@ -113,13 +118,14 @@ The above 6 lines of code are **all you need** to create this control:
113118

114119
![image](https://cloud.githubusercontent.com/assets/4073988/5910789/e102af28-a572-11e4-9169-b18555e20eab.png)
115120

116-
### TGPCamelLabels
121+
### CamelLabels
117122

118123
Besides font customization, `TGPCamelLabels` only requires a set of labels (supplied as *strings*), and an active index selection.
119124

120125
**Step 1**: *tell* the TGPCamelLabels what to select
126+
_(Refer to **Single step** section above to use DiscreteSlider + CamelLabels in tandem)_
121127
```
122-
[self.camelLabels setValue:sender.value];
128+
camelLabels.value = sender.value
123129
```
124130

125131
*There is no step 2.*
@@ -129,20 +135,20 @@ Most of the customization can be done inside **Interface Builder**.
129135

130136
| Property | |
131137
|:---------| ----- |
132-
| `ticksListener` | ties a discrete slider to its camel labels. This is your most robust method to not only ensure that the layout of both controls match exactly, but also adjust this spacing when orientation changes. A typical use may be `self.discreteSlider.ticksListener = self.camelLabels` |
133-
| `names` | supplies a new set of labels ; supersedes the `tickCount` property, which will return the number of labels. A typical use may be `self.camelLabels.names = @[@"OFF", @"ON"]` |
134-
| `ticksDistance` | _override_ the labels spacing entirely ; **prefer** the `ticksListener` mechanism if it is available to you. A typical use may be `self.camelLabels.ticksDistance = 15` |
138+
| `ticksListener` | ties a discrete slider to its camel labels. This is your most robust method to not only ensure that the layout of both controls match exactly, but also adjust this spacing when orientation changes. A typical use may be `discreteSlider.ticksListener = camelLabels` |
139+
| `names` | supplies a new set of labels ; supersedes the `tickCount` property, which will return the number of labels. A typical use may be `camelLabels.names = ["OFF", "ON"]` |
140+
| `ticksDistance` | _override_ the labels spacing entirely ; **prefer** the `ticksListener` mechanism if it is available to you. A typical use may be `camelLabels.ticksDistance = 15` |
135141
| `value` | which label is emphasized (_selected_) |
136-
| `backgroundColor` | labels become *tap-through* (**click-through**) when set to `clearColor` ; use TGPCamelLabels *on top of* other UI elements, **even native iOS objects**!:![uiswitch](https://cloud.githubusercontent.com/assets/4073988/11609813/a3b63526-9b45-11e5-9562-34fc2c9b134d.gif) |
142+
| `backgroundColor` | labels become *tap-through* (**click-through**) when set to `UIColor.clear` ; use TGPCamelLabels *on top of* other UI elements, **even native iOS objects**!:![uiswitch](https://cloud.githubusercontent.com/assets/4073988/11609813/a3b63526-9b45-11e5-9562-34fc2c9b134d.gif) |
137143

138144
| Edges & Animation | |
139145
|:------------------| ----- |
140146
| `offCenter` | **leftmost and righmost labels only**: relative inset expressed as a proportion of individual label width: 0: none, +0.5: nudge in by a half width (fully fit) or -0.5: draw completely outside |
141147
| `insets` | **leftmost and righmost labels only**: absolute inset expressed in pixels |
142-
| `emphasisLayout` | emphasized (_selected_) labels vertical alignment ; `top`, `centerY` or `bottom`. Default is `top` (†) |
143-
| `regularLayout` | regular labels vertical alignment ; `top`, `centerY` or `bottom`. Default is `bottom` (†) |
148+
| `emphasisLayout` | emphasized (_selected_) labels vertical alignment ; `.top`, `.centerY` or `.bottom`. Default is `.top` (†) |
149+
| `regularLayout` | regular labels vertical alignment ; `.top`, `.centerY` or `.bottom`. Default is `.bottom` (†) |
144150

145-
(†) No camel animation will occur when `emphasisLayout` = `regularLayout`, i.e. `centerY`.
151+
(†) No camel animation will occur when `emphasisLayout` = `regularLayout`, i.e. `.centerY`.
146152

147153
| Emphasized labels | |
148154
|:------------------| ----- |
@@ -158,53 +164,41 @@ Most of the customization can be done inside **Interface Builder**.
158164

159165
### Code example
160166

161-
See **TGPControlsDemo** projects:
162-
1. `TGPControlsDemo` (iOS 9 & 8 + Swift + IBInspectable)
163-
2. `TGPControlsDemo7` (iOS 7 + ObjC) projects.
167+
See **TGPControlsDemo** project: `TGPControlsDemo` (Modern Swift syntax + IBInspectable)
164168

165169
```
166-
#import "ViewController.h"
167-
#import "TGPDiscreteSlider.h"
168-
#import "TGPCamelLabels.h"
169-
170-
@interface ViewController ()
171-
@property (strong, nonatomic) IBOutlet TGPDiscreteSlider *oneTo10Slider;
172-
@property (strong, nonatomic) IBOutlet TGPCamelLabels *oneTo10Labels;
173-
174-
@property (strong, nonatomic) IBOutlet TGPCamelLabels *alphabetLabels;
175-
@property (strong, nonatomic) IBOutlet TGPDiscreteSlider *alphabetSlider;
176-
177-
@property (strong, nonatomic) IBOutlet TGPCamelLabels *switch1Camel;
178-
@property (strong, nonatomic) IBOutlet TGPCamelLabels *switch2Camel;
179-
@end
180-
181-
@implementation ViewController
182-
183-
- (void)viewDidLoad {
184-
[super viewDidLoad];
185-
186-
self.alphabetLabels.names = @[@"A",@"B",@"C",@"D",@"E",@"F", @"G",@"H",@"I",@"J",@"K",@"L",@"M",
187-
@"N",@"O",@"P",@"Q",@"R",@"S", @"T",@"U",@"V",@"W",@"X",@"Y",@"Z"];
188-
self.switch1Camel.names = @[@"OFF", @"ON"];
189-
190-
// Automatically track tick spacing changes
191-
self.alphabetSlider.ticksListener = self.alphabetLabels;
192-
self.oneTo10Slider.ticksListener = self.oneTo10Labels;
170+
import UIKit
171+
import TGPControls
172+
173+
class ViewController: UIViewController {
174+
@IBOutlet weak var oneTo10Labels: TGPCamelLabels!
175+
@IBOutlet weak var oneTo10Slider: TGPDiscreteSlider!
176+
@IBOutlet weak var alphabetLabels: TGPCamelLabels!
177+
@IBOutlet weak var alphabetSlider: TGPDiscreteSlider!
178+
@IBOutlet weak var switch1Camel: TGPCamelLabels!
179+
180+
override func viewDidLoad() {
181+
super.viewDidLoad()
182+
183+
alphabetLabels.names = ["A","B","C","D","E","F",
184+
"G","H","I","J","K","L","M",
185+
"N","O","P","Q","R","S",
186+
"T","U","V","W","X","Y","Z"]
187+
switch1Camel.names = ["OFF", "ON"]
188+
189+
// Automatically track tick spacing and value changes
190+
alphabetSlider.ticksListener = alphabetLabels
191+
oneTo10Slider.ticksListener = oneTo10Labels
193192
}
194193
195-
#pragma mark UISwitch
194+
// MARK: - UISwitch
196195
197-
- (IBAction)switch1ValueChanged:(UISwitch *)sender {
198-
[self.switch1Camel setValue:((sender.isOn) ? 1 : 0)];
196+
@IBAction func switch1ValueChanged(_ sender: UISwitch) {
197+
switch1Camel.value = (sender.isOn) ? 1 : 0
199198
}
200-
201-
- (IBAction)switch2TouchUpInside:(UISwitch *)sender {
202-
[self.switch2Camel setValue:((sender.isOn) ? 1 : 0)];
203199
}
204-
205-
@end
206200
```
207-
### Customization example
201+
### Customization examples
208202

209203
![image](https://cloud.githubusercontent.com/assets/4073988/5909892/7fdc091e-a569-11e4-906b-da0f185a1b91.png)
210204

TGPControls.podspec

Lines changed: 17 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,98 +1,35 @@
1-
#
2-
# Be sure to run `pod spec lint TGPControls.podspec' to ensure this is a
3-
# valid spec and to remove all comments including this before submitting the spec.
4-
#
5-
# To learn more about Podspec attributes see http://docs.cocoapods.org/specification.html
6-
# To see working Podspecs in the CocoaPods repo see https://github.com/CocoaPods/Specs/
7-
#
8-
9-
Pod::Spec.new do |s|
1+
Pod::Spec.new do |spec|
102

113
# ――― Spec Metadata ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
12-
#
13-
# These will help people to find your library, and whilst it
14-
# can feel like a chore to fill in it's definitely to your advantage. The
15-
# summary should be tweet-length, and the description more in depth.
16-
#
17-
18-
s.name = "TGPControls"
19-
s.version = "2.1.0"
20-
s.summary = "Custom Awesome iOS Controls: Animated discrete slider, animated labels"
4+
spec.name = "TGPControls"
5+
spec.version = "3.0.0"
6+
spec.summary = "Custom animated iOS controls: Animated discrete slider, animated labels"
217

22-
s.description = <<-DESC
8+
spec.description = <<-DESC
239
Provide an iOS looking UISlider with discrete, controlable steps
2410
Provide dynamic, animated labels for discrete slider
2511
Entirely compatible with UISlider
26-
2712
DESC
28-
29-
s.homepage = "https://github.com/arquebuse/TGPControls"
30-
s.screenshots = "https://cloud.githubusercontent.com/assets/4073988/5912371/144aaf24-a588-11e4-9a22-42832eb2c235.gif", "https://cloud.githubusercontent.com/assets/4073988/5912454/15774398-a589-11e4-8f08-18c9c7b59871.gif", "https://cloud.githubusercontent.com/assets/4073988/6628373/183c7452-c8c2-11e4-9a63-107805bc0cc4.gif", "https://cloud.githubusercontent.com/assets/4073988/5912297/c3f21bb2-a586-11e4-8eb1-a1f930ccbdd5.gif"
31-
13+
spec.homepage = "https://github.com/SwiftArchitect/TGPControls"
14+
spec.screenshots = "https://cloud.githubusercontent.com/assets/4073988/5912371/144aaf24-a588-11e4-9a22-42832eb2c235.gif", "https://cloud.githubusercontent.com/assets/4073988/5912454/15774398-a589-11e4-8f08-18c9c7b59871.gif", "https://cloud.githubusercontent.com/assets/4073988/6628373/183c7452-c8c2-11e4-9a63-107805bc0cc4.gif", "https://cloud.githubusercontent.com/assets/4073988/5912297/c3f21bb2-a586-11e4-8eb1-a1f930ccbdd5.gif"
3215

3316
# ――― Spec License ――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
34-
#
35-
# Licensing your code is important. See http://choosealicense.com for more info.
36-
# CocoaPods will detect a license file if there is a named LICENSE*
37-
# Popular ones are 'MIT', 'BSD' and 'Apache License, Version 2.0'.
38-
#
39-
40-
# s.license = "MIT (example)"
41-
s.license = { :type => "MIT", :file => "TGPControls_License.txt" }
42-
17+
spec.license = { :type => "MIT", :file => "LICENSE" }
4318

4419
# ――― Author Metadata ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
45-
#
46-
# Specify the authors of the library, with email addresses. Email addresses
47-
# of the authors are extracted from the SCM log. E.g. $ git log. CocoaPods also
48-
# accepts just a name if you'd rather not provide an email address.
49-
#
50-
# Specify a social_media_url where others can refer to, for example a twitter
51-
# profile URL.
52-
#
53-
54-
s.author = { "Xavier Schott" => "http://swiftarchitect.com/swiftarchitect/" }
55-
s.social_media_url = "https://twitter.com/swiftarchitect"
56-
20+
spec.author = { "Xavier Schott" => "http://swiftarchitect.com/swiftarchitect/" }
5721

5822
# ――― Platform Specifics ――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
59-
#
60-
# If this Pod runs only on iOS or OS X, then specify the platform and
61-
# the deployment target. You can optionally include the target after the platform.
62-
#
63-
64-
s.platform = :ios, "7.0"
65-
23+
spec.platform = :ios
24+
spec.ios.deployment_target = '8.0'
25+
spec.requires_arc = true
6626

6727
# ――― Source Location ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
68-
#
69-
# Specify the location from where the source should be retrieved.
70-
# Supports git, hg, bzr, svn and HTTP.
71-
#
72-
73-
s.source = { :git => "https://github.com/SwiftArchitect/TGPControls.git", :tag => "v2.1.0" }
74-
75-
76-
# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
77-
#
78-
# CocoaPods is smart about how it includes source code. For source files
79-
# giving a folder will include any h, m, mm, c & cpp files. For header
80-
# files it will include any header in the folder.
81-
# Not including the public_header_files will make all headers public.
82-
#
83-
84-
s.source_files = "TGPControls", "TGPControls/**/*.{h,m}"
85-
s.exclude_files = "TGPControlsDemo7/*", "TGPControlsDemo/*"
86-
s.public_header_files = "TGPControls/**/*.{h}"
87-
88-
89-
# ――― Project Settings ――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
90-
#
91-
# If your library depends on compiler flags you can set them in the xcconfig hash
92-
# where they will only apply to your library. If you depend on other Podspecs
93-
# you can include multiple dependencies to ensure it works.
94-
95-
s.requires_arc = true
28+
spec.source = { :git => "https://github.com/SwiftArchitect/TGPControls.git", :tag => "v3.0.0" }
29+
spec.source_files = "TGPControls/**/*.{swift}"
30+
spec.exclude_files = "TGPControlsDemo/*"
9631

32+
# ――― Project Linking ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
33+
spec.framework = "UIKit"
9734

9835
end

0 commit comments

Comments
 (0)