Skip to content

Commit 524d4fd

Browse files
committed
Add public interface to customize text attributes
1 parent 3bc15c6 commit 524d4fd

5 files changed

Lines changed: 144 additions & 6 deletions

File tree

Example/Example.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
154CE52873EEBDF8EF05A61F /* Pods_Example.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D0DB1D3E89AB75183DB104E0 /* Pods_Example.framework */; };
11+
B52819581C90215C007D01D5 /* CustomizedTokenField.swift in Sources */ = {isa = PBXBuildFile; fileRef = B52819571C90215C007D01D5 /* CustomizedTokenField.swift */; };
1112
B548C5A71C8D55A8009D5AEE /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = B548C5A51C8D55A8009D5AEE /* InfoPlist.strings */; };
1213
B548C5A91C8D6150009D5AEE /* ExampleCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = B548C5A81C8D6150009D5AEE /* ExampleCell.swift */; };
1314
B548C5C51C8E91B0009D5AEE /* ICInputAccessoryUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = B548C5C41C8E91B0009D5AEE /* ICInputAccessoryUITests.swift */; };
@@ -28,6 +29,7 @@
2829
/* End PBXContainerItemProxy section */
2930

3031
/* Begin PBXFileReference section */
32+
B52819571C90215C007D01D5 /* CustomizedTokenField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CustomizedTokenField.swift; sourceTree = "<group>"; };
3133
B548C5A61C8D55A8009D5AEE /* Base */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = Base; path = Base.lproj/InfoPlist.strings; sourceTree = "<group>"; };
3234
B548C5A81C8D6150009D5AEE /* ExampleCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExampleCell.swift; sourceTree = "<group>"; };
3335
B548C5C21C8E91B0009D5AEE /* ICInputAccessoryUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ICInputAccessoryUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
@@ -114,6 +116,7 @@
114116
children = (
115117
B5E9F8FE1C8D3B6E00443DC7 /* AppDelegate.swift */,
116118
B5E9F9051C8D3B6E00443DC7 /* Assets.xcassets */,
119+
B52819571C90215C007D01D5 /* CustomizedTokenField.swift */,
117120
B548C5A81C8D6150009D5AEE /* ExampleCell.swift */,
118121
B5E9F9001C8D3B6E00443DC7 /* ExampleViewController.swift */,
119122
B5E9F90A1C8D3B6E00443DC7 /* Info.plist */,
@@ -299,6 +302,7 @@
299302
buildActionMask = 2147483647;
300303
files = (
301304
B5E9F8FF1C8D3B6E00443DC7 /* AppDelegate.swift in Sources */,
305+
B52819581C90215C007D01D5 /* CustomizedTokenField.swift in Sources */,
302306
B548C5A91C8D6150009D5AEE /* ExampleCell.swift in Sources */,
303307
B5E9F9011C8D3B6E00443DC7 /* ExampleViewController.swift in Sources */,
304308
);
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
//
2+
// CustomizedTokenField.swift
3+
// Example
4+
//
5+
// Created by Ben on 09/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+
import ICInputAccessory
29+
30+
class CustomizedTokenField: UIView {
31+
32+
override init(frame: CGRect) {
33+
super.init(frame: frame)
34+
setUpSubviews()
35+
}
36+
37+
required init?(coder aDecoder: NSCoder) {
38+
super.init(coder: aDecoder)
39+
setUpSubviews()
40+
}
41+
42+
private func setUpSubviews() {
43+
backgroundColor = UIColor(red:0.96, green:0.48, blue:0.4, alpha:1)
44+
45+
let tokenField = ICTokenField()
46+
tokenField.applyCustomizedStyle()
47+
tokenField.translatesAutoresizingMaskIntoConstraints = false
48+
addSubview(tokenField)
49+
50+
let views = ["field": tokenField]
51+
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-10-[field]-10-|", options: [], metrics: nil, views: views))
52+
addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-3-[field]-3-|", options: [], metrics: nil, views: views))
53+
}
54+
55+
}
56+
57+
58+
////////////////////////////////////////////////////////////////////////////////
59+
60+
61+
extension ICTokenField {
62+
63+
func applyCustomizedStyle() {
64+
layer.cornerRadius = 5
65+
layer.shouldRasterize = true
66+
layer.rasterizationScale = UIScreen.mainScreen().scale
67+
backgroundColor = UIColor(red:0.8, green:0.32, blue:0.24, alpha:1)
68+
69+
textField.textColor = UIColor.whiteColor()
70+
textField.tintColor = UIColor.whiteColor()
71+
textField.font = UIFont.boldSystemFontOfSize(14)
72+
73+
attributedPlaceholder = NSAttributedString(
74+
string: String(self.dynamicType),
75+
attributes: [
76+
NSForegroundColorAttributeName: UIColor.whiteColor().colorWithAlphaComponent(0.5),
77+
NSFontAttributeName: UIFont.boldSystemFontOfSize(14)
78+
]
79+
)
80+
81+
normalTokenAttributes = [
82+
NSForegroundColorAttributeName: UIColor.whiteColor(),
83+
NSBackgroundColorAttributeName: UIColor.whiteColor().colorWithAlphaComponent(0.25),
84+
NSFontAttributeName: UIFont.boldSystemFontOfSize(14)
85+
]
86+
87+
highlightedTokenAttributes = [
88+
NSForegroundColorAttributeName: UIColor(red:0.8, green:0.32, blue:0.24, alpha:1),
89+
NSBackgroundColorAttributeName: UIColor.whiteColor(),
90+
NSFontAttributeName: UIFont.boldSystemFontOfSize(14)
91+
]
92+
}
93+
94+
}

Example/Example/ExampleViewController.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,11 @@ class ExampleViewController: UIViewController, UITableViewDataSource {
3737
return _tableView
3838
}()
3939

40-
private let types: [UIView.Type] = [ICKeyboardDismissTextField.self, ICTokenField.self]
40+
private let types: [UIView.Type] = [
41+
ICKeyboardDismissTextField.self,
42+
ICTokenField.self,
43+
CustomizedTokenField.self
44+
]
4145

4246
// MARK: - Initialization
4347

@@ -71,6 +75,8 @@ class ExampleViewController: UIViewController, UITableViewDataSource {
7175
return "Dismiss Keyboard"
7276
case is ICTokenField.Type:
7377
return "Text Field with Tokens"
78+
case is CustomizedTokenField.Type:
79+
return "Customize Token Field"
7480
default:
7581
return ""
7682
}
@@ -95,6 +101,9 @@ class ExampleViewController: UIViewController, UITableViewDataSource {
95101
container.addSubview(tokenField)
96102
(cell as? ExampleCell)?.showcase = container
97103

104+
case let type as CustomizedTokenField.Type:
105+
(cell as? ExampleCell)?.showcase = type.init()
106+
98107
default:
99108
break
100109
}

Source/ICToken.swift

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,21 @@ class ICToken: UIView {
4444
var normalTextAttributes: [String : NSObject] = [
4545
NSForegroundColorAttributeName: UIColor(red:0.14, green:0.38, blue:0.95, alpha:1),
4646
NSBackgroundColorAttributeName: UIColor.clearColor()
47-
]
47+
] {
48+
didSet {
49+
if !highlighted { updateTextLabel() }
50+
delimiterLabel.textColor = self.normalTextAttributes[NSForegroundColorAttributeName] as? UIColor
51+
}
52+
}
4853

4954
var highlightedTextAttributes: [String: NSObject] = [
5055
NSForegroundColorAttributeName: UIColor.whiteColor(),
5156
NSBackgroundColorAttributeName: UIColor(red:0.14, green:0.38, blue:0.95, alpha:1)
52-
]
57+
] {
58+
didSet {
59+
if highlighted { updateTextLabel() }
60+
}
61+
}
5362

5463
// MARK: - Private Properties
5564

@@ -81,8 +90,10 @@ class ICToken: UIView {
8190
setUpSubviews()
8291
}
8392

84-
convenience init(text: String) {
93+
convenience init(text: String, normalAttributes: [String: NSObject]? = nil, highlightedAttributes: [String: NSObject]? = nil) {
8594
self.init()
95+
if let attributes = normalAttributes { normalTextAttributes = attributes }
96+
if let attributes = highlightedAttributes { highlightedTextAttributes = attributes }
8697
// didSet is not called within the initializer
8798
setText(text)
8899
}
@@ -98,8 +109,12 @@ class ICToken: UIView {
98109
if let color = attributes[NSBackgroundColorAttributeName] as? UIColor {
99110
textLabel.backgroundColor = color
100111
}
112+
// Avoid overlapped translucent background colors
101113
attributes[NSBackgroundColorAttributeName] = nil
102114
textLabel.attributedText = NSAttributedString(string: text, attributes: attributes)
115+
116+
delimiterLabel.textColor = normalTextAttributes[NSForegroundColorAttributeName] as? UIColor
117+
delimiterLabel.font = normalTextAttributes[NSFontAttributeName] as? UIFont
103118
}
104119

105120
private func setUpSubviews() {

Source/ICTokenField.swift

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,8 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele
8484
}
8585
}
8686

87+
// MARK: - UI Customization
88+
8789
/// The placeholder with customized attributes.
8890
public var attributedPlaceholder: NSAttributedString? {
8991
didSet {
@@ -103,6 +105,20 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele
103105
}
104106
}
105107

108+
/// Customized attributes for tokens in the normal state, e.g. NSFontAttributeName and NSForegroundColorAttributeName.
109+
public var normalTokenAttributes: [String: NSObject]? {
110+
didSet {
111+
tokens.forEach { $0.normalTextAttributes = normalTokenAttributes ?? [:] }
112+
}
113+
}
114+
115+
/// Customized attributes for tokens in the highlighted state.
116+
public var highlightedTokenAttributes: [String: NSObject]? {
117+
didSet {
118+
tokens.forEach { $0.highlightedTextAttributes = normalTokenAttributes ?? [:] }
119+
}
120+
}
121+
106122
// MARK: - Private Properties
107123

108124
private var tokens = [ICToken]()
@@ -224,7 +240,7 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele
224240
textField.text = nil
225241

226242
if newToken != delimiter {
227-
tokens.append(ICToken(text: newToken))
243+
tokens.append(ICToken(text: newToken, normalAttributes: normalTokenAttributes, highlightedAttributes: highlightedTokenAttributes))
228244
layoutTokenTextField()
229245
delegate?.tokenField(self, didEnterText: newToken)
230246
}
@@ -369,7 +385,7 @@ public class ICTokenField: UIView, UITextFieldDelegate, ICBackspaceTextFieldDele
369385
return
370386
}
371387
inputTextField.text = nil
372-
tokens.append(ICToken(text: text))
388+
tokens.append(ICToken(text: text, normalAttributes: normalTokenAttributes, highlightedAttributes: highlightedTokenAttributes))
373389
layoutTokenTextField()
374390
delegate?.tokenField(self, didEnterText: text)
375391
}

0 commit comments

Comments
 (0)