Skip to content

Commit 2585e53

Browse files
committed
Import ICTokenField
1 parent a4909a4 commit 2585e53

6 files changed

Lines changed: 689 additions & 2 deletions

File tree

Example/Example/ExampleViewController.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ class ExampleViewController: UIViewController, UITableViewDataSource {
5353
view.addSubview(tableView)
5454
tableView.frame = view.bounds
5555
tableView.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
56+
let _ = ICTokenField()
5657
}
5758

5859
// MARK: - UITableViewDataSource

ICInputAccessory.xcodeproj/project.pbxproj

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,21 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
B528196C1C9035BE007D01D5 /* ICBackspaceTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52819681C9035BE007D01D5 /* ICBackspaceTextField.swift */; };
11+
B528196D1C9035BE007D01D5 /* ICInsetLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52819691C9035BE007D01D5 /* ICInsetLabel.swift */; };
12+
B528196E1C9035BE007D01D5 /* ICToken.swift in Sources */ = {isa = PBXBuildFile; fileRef = B528196A1C9035BE007D01D5 /* ICToken.swift */; };
13+
B528196F1C9035BE007D01D5 /* ICTokenField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B528196B1C9035BE007D01D5 /* ICTokenField.swift */; };
1014
B548C5AD1C8D69A5009D5AEE /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = B548C5AC1C8D69A5009D5AEE /* Images.xcassets */; };
1115
B548C5EE1C8EB9E2009D5AEE /* ICKeyboardDismissTextField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B548C5ED1C8EB9E2009D5AEE /* ICKeyboardDismissTextField.swift */; };
1216
B56BC42E1C89A7EA00C20AD6 /* ICInputAccessory.h in Headers */ = {isa = PBXBuildFile; fileRef = B56BC42D1C89A7EA00C20AD6 /* ICInputAccessory.h */; settings = {ATTRIBUTES = (Public, ); }; };
1317
B56BC4361C89A8D800C20AD6 /* ICKeyboardDismissAccessoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B56BC4351C89A8D800C20AD6 /* ICKeyboardDismissAccessoryView.swift */; };
1418
/* End PBXBuildFile section */
1519

1620
/* Begin PBXFileReference section */
21+
B52819681C9035BE007D01D5 /* ICBackspaceTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ICBackspaceTextField.swift; path = Source/ICBackspaceTextField.swift; sourceTree = SOURCE_ROOT; };
22+
B52819691C9035BE007D01D5 /* ICInsetLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ICInsetLabel.swift; path = Source/ICInsetLabel.swift; sourceTree = SOURCE_ROOT; };
23+
B528196A1C9035BE007D01D5 /* ICToken.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ICToken.swift; path = Source/ICToken.swift; sourceTree = SOURCE_ROOT; };
24+
B528196B1C9035BE007D01D5 /* ICTokenField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ICTokenField.swift; path = Source/ICTokenField.swift; sourceTree = SOURCE_ROOT; };
1725
B548C5AC1C8D69A5009D5AEE /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = Source/Images.xcassets; sourceTree = SOURCE_ROOT; };
1826
B548C5ED1C8EB9E2009D5AEE /* ICKeyboardDismissTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ICKeyboardDismissTextField.swift; path = Source/ICKeyboardDismissTextField.swift; sourceTree = SOURCE_ROOT; };
1927
B56BC42A1C89A7EA00C20AD6 /* ICInputAccessory.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ICInputAccessory.framework; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -33,6 +41,26 @@
3341
/* End PBXFrameworksBuildPhase section */
3442

3543
/* Begin PBXGroup section */
44+
B52819671C90358C007D01D5 /* ICKeyboardDismissAccessory */ = {
45+
isa = PBXGroup;
46+
children = (
47+
B56BC4351C89A8D800C20AD6 /* ICKeyboardDismissAccessoryView.swift */,
48+
B548C5ED1C8EB9E2009D5AEE /* ICKeyboardDismissTextField.swift */,
49+
);
50+
name = ICKeyboardDismissAccessory;
51+
sourceTree = "<group>";
52+
};
53+
B52819701C9035C3007D01D5 /* ICTokenField */ = {
54+
isa = PBXGroup;
55+
children = (
56+
B52819681C9035BE007D01D5 /* ICBackspaceTextField.swift */,
57+
B52819691C9035BE007D01D5 /* ICInsetLabel.swift */,
58+
B528196A1C9035BE007D01D5 /* ICToken.swift */,
59+
B528196B1C9035BE007D01D5 /* ICTokenField.swift */,
60+
);
61+
name = ICTokenField;
62+
sourceTree = "<group>";
63+
};
3664
B56BC4201C89A7EA00C20AD6 = {
3765
isa = PBXGroup;
3866
children = (
@@ -52,9 +80,9 @@
5280
B56BC42C1C89A7EA00C20AD6 /* ICInputAccessory */ = {
5381
isa = PBXGroup;
5482
children = (
83+
B52819671C90358C007D01D5 /* ICKeyboardDismissAccessory */,
84+
B52819701C9035C3007D01D5 /* ICTokenField */,
5585
B56BC42D1C89A7EA00C20AD6 /* ICInputAccessory.h */,
56-
B56BC4351C89A8D800C20AD6 /* ICKeyboardDismissAccessoryView.swift */,
57-
B548C5ED1C8EB9E2009D5AEE /* ICKeyboardDismissTextField.swift */,
5886
B548C5AC1C8D69A5009D5AEE /* Images.xcassets */,
5987
B56BC42F1C89A7EA00C20AD6 /* Info.plist */,
6088
);
@@ -140,8 +168,12 @@
140168
isa = PBXSourcesBuildPhase;
141169
buildActionMask = 2147483647;
142170
files = (
171+
B528196C1C9035BE007D01D5 /* ICBackspaceTextField.swift in Sources */,
172+
B528196D1C9035BE007D01D5 /* ICInsetLabel.swift in Sources */,
143173
B56BC4361C89A8D800C20AD6 /* ICKeyboardDismissAccessoryView.swift in Sources */,
144174
B548C5EE1C8EB9E2009D5AEE /* ICKeyboardDismissTextField.swift in Sources */,
175+
B528196E1C9035BE007D01D5 /* ICToken.swift in Sources */,
176+
B528196F1C9035BE007D01D5 /* ICTokenField.swift in Sources */,
145177
);
146178
runOnlyForDeploymentPostprocessing = 0;
147179
};

Source/ICBackspaceTextField.swift

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
//
2+
// ICBackspaceTextField.swift
3+
// iCook
4+
//
5+
// Created by Ben on 02/03/2016.
6+
// Copyright © 2016 Polydice, Inc.
7+
//
8+
// Permission is hereby granted, free of charge, to any person obtaining a copy
9+
// of this software and associated documentation files (the "Software"), to deal
10+
// in the Software without restriction, including without limitation the rights
11+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
// copies of the Software, and to permit persons to whom the Software is
13+
// furnished to do so, subject to the following conditions:
14+
//
15+
// The above copyright notice and this permission notice shall be included in all
16+
// copies or substantial portions of the Software.
17+
//
18+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
// SOFTWARE.
25+
//
26+
27+
import UIKit
28+
29+
protocol ICBackspaceTextFieldDelegate: class {
30+
func textFieldShouldDelete(textField: ICBackspaceTextField) -> Bool
31+
}
32+
33+
////////////////////////////////////////////////////////////////////////////////
34+
35+
36+
class ICBackspaceTextField: UITextField {
37+
38+
weak var backspaceDelegate: ICBackspaceTextFieldDelegate?
39+
40+
var showsCursor = true {
41+
didSet {
42+
// Trigger the lazy instantiation of cursorColor
43+
let color = cursorColor
44+
tintColor = showsCursor ? color : UIColor.clearColor()
45+
}
46+
}
47+
48+
lazy var cursorColor: UIColor! = { self.tintColor }()
49+
50+
// MARK: - UIView
51+
52+
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
53+
// Forward touches to the superview when the cursor is hidden.
54+
return showsCursor && super.pointInside(point, withEvent: event)
55+
}
56+
57+
// MARK: - UITextField
58+
59+
func keyboardInputShouldDelete(textField: UITextField) -> Bool {
60+
return backspaceDelegate?.textFieldShouldDelete(self) ?? true
61+
}
62+
63+
}

Source/ICInsetLabel.swift

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
//
2+
// ICInsetLabel.swift
3+
// iCook
4+
//
5+
// Created by Ben on 10/07/2015.
6+
// Copyright (c) 2015 Polydice, Inc.
7+
//
8+
// Permission is hereby granted, free of charge, to any person obtaining a copy
9+
// of this software and associated documentation files (the "Software"), to deal
10+
// in the Software without restriction, including without limitation the rights
11+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
// copies of the Software, and to permit persons to whom the Software is
13+
// furnished to do so, subject to the following conditions:
14+
//
15+
// The above copyright notice and this permission notice shall be included in all
16+
// copies or substantial portions of the Software.
17+
//
18+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
// SOFTWARE.
25+
//
26+
27+
import UIKit
28+
29+
class ICInsetLabel: UILabel {
30+
31+
enum CornerRadius {
32+
case Dynamic
33+
case Constant(CGFloat)
34+
}
35+
36+
var contentEdgeInsets = UIEdgeInsetsZero
37+
var cornerRadius = CornerRadius.Constant(0)
38+
39+
convenience init(contentEdgeInsets: UIEdgeInsets, cornerRadius: CornerRadius = .Constant(0)) {
40+
self.init(frame: CGRect.zero)
41+
self.contentEdgeInsets = contentEdgeInsets
42+
self.cornerRadius = cornerRadius
43+
44+
switch cornerRadius {
45+
case .Constant(let radius) where radius > 0:
46+
layer.cornerRadius = radius
47+
fallthrough
48+
case .Dynamic:
49+
layer.masksToBounds = true
50+
layer.shouldRasterize = true
51+
layer.rasterizationScale = UIScreen.mainScreen().scale
52+
default:
53+
break
54+
}
55+
}
56+
57+
// MARK: - UIView
58+
59+
override func intrinsicContentSize() -> CGSize {
60+
let size = super.intrinsicContentSize()
61+
return CGSize(
62+
width: contentEdgeInsets.left + size.width + contentEdgeInsets.right,
63+
height: contentEdgeInsets.top + size.height + contentEdgeInsets.bottom
64+
)
65+
}
66+
67+
override func layoutSubviews() {
68+
super.layoutSubviews()
69+
if case .Dynamic = cornerRadius {
70+
layer.cornerRadius = frame.height / 2
71+
}
72+
}
73+
74+
}

Source/ICToken.swift

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
//
2+
// ICToken.swift
3+
// iCook
4+
//
5+
// Created by Ben on 03/03/2016.
6+
// Copyright © 2016 Polydice, Inc.
7+
//
8+
// Permission is hereby granted, free of charge, to any person obtaining a copy
9+
// of this software and associated documentation files (the "Software"), to deal
10+
// in the Software without restriction, including without limitation the rights
11+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
// copies of the Software, and to permit persons to whom the Software is
13+
// furnished to do so, subject to the following conditions:
14+
//
15+
// The above copyright notice and this permission notice shall be included in all
16+
// copies or substantial portions of the Software.
17+
//
18+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24+
// SOFTWARE.
25+
//
26+
27+
import UIKit
28+
29+
class ICToken: UIView {
30+
31+
var text = "" {
32+
didSet {
33+
updateTextLabel()
34+
frame = CGRect(origin: CGPoint.zero, size: systemLayoutSizeFittingSize(UILayoutFittingCompressedSize))
35+
}
36+
}
37+
38+
var highlighted = false {
39+
didSet {
40+
updateTextLabel()
41+
}
42+
}
43+
44+
var normalTextAttributes: [String : NSObject] = [
45+
NSForegroundColorAttributeName: UIColor.whiteColor(),
46+
NSBackgroundColorAttributeName: UIColor.whiteColor().colorWithAlphaComponent(0.25)
47+
]
48+
49+
var highlightedTextAttributes: [String: NSObject] = [
50+
NSForegroundColorAttributeName: UIColor(red:0.8, green:0.32, blue:0.24, alpha:1),
51+
NSBackgroundColorAttributeName: UIColor.whiteColor()
52+
]
53+
54+
// MARK: - Private Properties
55+
56+
private(set) lazy var delimiterLabel: UILabel = {
57+
let _delimiter = UILabel()
58+
_delimiter.text = " , "
59+
_delimiter.textColor = UIColor.whiteColor()
60+
return _delimiter
61+
}()
62+
63+
private(set) lazy var textLabel: UILabel = {
64+
let _label = ICInsetLabel(contentEdgeInsets: UIEdgeInsets(top: 3, left: 5, bottom: 3, right: 5), cornerRadius: .Constant(3))
65+
_label.textAlignment = .Center
66+
_label.textColor = self.normalTextAttributes[NSForegroundColorAttributeName] as? UIColor
67+
_label.backgroundColor = self.normalTextAttributes[NSBackgroundColorAttributeName] as? UIColor
68+
_label.numberOfLines = 1
69+
return _label
70+
}()
71+
72+
// MARK: - Initialization
73+
74+
override init(frame: CGRect) {
75+
super.init(frame: frame)
76+
setUpSubviews()
77+
}
78+
79+
required init?(coder aDecoder: NSCoder) {
80+
super.init(coder: aDecoder)
81+
setUpSubviews()
82+
}
83+
84+
convenience init(text: String) {
85+
self.init()
86+
// didSet is not called within the initializer
87+
setText(text)
88+
}
89+
90+
private func setText(text: String) {
91+
self.text = text
92+
}
93+
94+
// MARK: - Private Methods
95+
96+
private func updateTextLabel() {
97+
var attributes = highlighted ? highlightedTextAttributes : normalTextAttributes
98+
if let color = attributes[NSBackgroundColorAttributeName] as? UIColor {
99+
textLabel.backgroundColor = color
100+
}
101+
attributes[NSBackgroundColorAttributeName] = nil
102+
textLabel.attributedText = NSAttributedString(string: text, attributes: attributes)
103+
}
104+
105+
private func setUpSubviews() {
106+
addSubview(textLabel)
107+
addSubview(delimiterLabel)
108+
textLabel.translatesAutoresizingMaskIntoConstraints = false
109+
delimiterLabel.translatesAutoresizingMaskIntoConstraints = false
110+
111+
let views = [
112+
"text": textLabel,
113+
"delimiter": delimiterLabel
114+
]
115+
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[text][delimiter]|",
116+
options: [.AlignAllCenterY],
117+
metrics: nil,
118+
views: views
119+
))
120+
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-2-[text]-2-|",
121+
options: [],
122+
metrics: nil,
123+
views: views
124+
))
125+
}
126+
127+
}

0 commit comments

Comments
 (0)