Skip to content

Commit 3e56b41

Browse files
lenkaiserrnystrom
authored andcommitted
Feature/add left button optional (#33)
* Add left button * Changed minimum requirement to iOS 9.0 * Added accessory button and flag to show or hide this button * Make MessageView listen to font changes for all buttons * Set preferred font size * Version bump * remove project files * Remove project files
1 parent 2e95527 commit 3e56b41

File tree

7 files changed

+162
-37
lines changed

7 files changed

+162
-37
lines changed

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@
8484
"idiom" : "ipad",
8585
"size" : "83.5x83.5",
8686
"scale" : "2x"
87+
},
88+
{
89+
"idiom" : "ios-marketing",
90+
"size" : "1024x1024",
91+
"scale" : "1x"
8792
}
8893
],
8994
"info" : {
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"version" : 1,
4+
"author" : "xcode"
5+
}
6+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "universal",
5+
"filename" : "attachment.png",
6+
"scale" : "1x"
7+
},
8+
{
9+
"idiom" : "universal",
10+
"filename" : "attachment@2x.png",
11+
"scale" : "2x"
12+
},
13+
{
14+
"idiom" : "universal",
15+
"scale" : "3x"
16+
}
17+
],
18+
"info" : {
19+
"version" : 1,
20+
"author" : "xcode"
21+
}
22+
}
Loading
Loading

Examples/Examples/ViewController.swift

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,21 @@ class ViewController: MessageViewController, UITableViewDataSource, UITableViewD
2525

2626
borderColor = .lightGray
2727

28-
messageView.inset = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16)
28+
messageView.inset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 16)
29+
messageView.font = UIFont.preferredFont(forTextStyle: .body)
30+
messageView.buttonLeftInset = 8
31+
32+
messageView.set(buttonIcon: UIImage(named: "attachment"), for: .normal, type: .left)
33+
messageView.addButton(target: self, action: #selector(onLeftButton), type: .left)
34+
messageView.showLeftButton = true
35+
2936
messageView.textView.placeholderText = "New message..."
3037
messageView.textView.placeholderTextColor = .lightGray
31-
messageView.font = UIFont.systemFont(ofSize: 17)
38+
messageView.textView.backgroundColor = .white
3239

33-
messageView.set(buttonTitle: "Send", for: .normal)
34-
messageView.addButton(target: self, action: #selector(onButton))
35-
messageView.buttonTint = .blue
40+
messageView.set(buttonTitle: "Send", for: .normal, type: .right)
41+
messageView.addButton(target: self, action: #selector(onRightButton), type: .right)
42+
messageView.rightButtonTint = .blue
3643

3744
messageAutocompleteController.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
3845
messageAutocompleteController.tableView.dataSource = self
@@ -52,7 +59,11 @@ class ViewController: MessageViewController, UITableViewDataSource, UITableViewD
5259
setup(scrollView: tableView)
5360
}
5461

55-
@objc func onButton() {
62+
@objc func onLeftButton() {
63+
print("Did press left button")
64+
}
65+
66+
@objc func onRightButton() {
5667
data.append(messageView.text)
5768
messageView.text = ""
5869
tableView.reloadData()

MessageViewController/MessageView.swift

Lines changed: 112 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,44 @@ public final class MessageView: UIView, MessageTextViewListener {
1313
public let textView = MessageTextView()
1414

1515
internal weak var delegate: MessageViewDelegate?
16-
internal let button = UIButton()
16+
internal let leftButton = UIButton()
17+
internal let rightButton = UIButton()
1718
internal let UITextViewContentSizeKeyPath = #keyPath(UITextView.contentSize)
1819
internal let topBorderLayer = CALayer()
1920
internal var contentView: UIView?
20-
internal var buttonAction: Selector?
21+
internal var leftButtonAction: Selector?
22+
internal var rightButtonAction: Selector?
23+
public var showLeftButton: Bool = true
24+
25+
public enum buttonType {
26+
case left
27+
case right
28+
}
2129

2230
internal override init(frame: CGRect) {
2331
super.init(frame: frame)
2432

2533
backgroundColor = .white
2634

35+
addSubview(leftButton)
2736
addSubview(textView)
28-
addSubview(button)
37+
addSubview(rightButton)
2938
layer.addSublayer(topBorderLayer)
3039

40+
//Set action button
41+
leftButton.imageEdgeInsets = .zero
42+
leftButton.titleEdgeInsets = .zero
43+
leftButton.contentEdgeInsets = .zero
44+
leftButton.titleLabel?.font = self.font ?? UIFont.systemFont(ofSize: 14)
45+
leftButton.imageView?.contentMode = .scaleAspectFit
46+
leftButton.imageView?.clipsToBounds = true
47+
3148
// setup text view
3249
textView.contentInset = .zero
3350
textView.textContainerInset = .zero
3451
textView.backgroundColor = .clear
3552
textView.addObserver(self, forKeyPath: UITextViewContentSizeKeyPath, options: [.new], context: nil)
36-
textView.font = .systemFont(ofSize: UIFont.systemFontSize)
53+
textView.font = self.font ?? UIFont.systemFont(ofSize: 14)
3754
textView.add(listener: self)
3855

3956
// setup TextKit props to defaults
@@ -47,9 +64,12 @@ public final class MessageView: UIView, MessageTextViewListener {
4764
textView.layoutManager.usesFontLeading = true
4865

4966
// setup send button
50-
button.titleEdgeInsets = .zero
51-
button.contentEdgeInsets = .zero
52-
button.imageEdgeInsets = .zero
67+
rightButton.imageEdgeInsets = .zero
68+
rightButton.titleEdgeInsets = .zero
69+
rightButton.contentEdgeInsets = .zero
70+
rightButton.titleLabel?.font = self.font ?? UIFont.systemFont(ofSize: 14)
71+
rightButton.imageView?.contentMode = .scaleAspectFit
72+
rightButton.imageView?.clipsToBounds = true
5373

5474
updateEmptyTextStates()
5575
}
@@ -67,6 +87,8 @@ public final class MessageView: UIView, MessageTextViewListener {
6787
public var font: UIFont? {
6888
get { return textView.font }
6989
set {
90+
leftButton.titleLabel?.font = newValue
91+
rightButton.titleLabel?.font = newValue
7092
textView.font = newValue
7193
delegate?.wantsLayout(messageView: self)
7294
}
@@ -92,22 +114,60 @@ public final class MessageView: UIView, MessageTextViewListener {
92114
didSet { setNeedsLayout() }
93115
}
94116

95-
public func set(buttonIcon: UIImage?, for state: UIControlState) {
96-
button.setImage(buttonIcon, for: state)
117+
public func set(buttonIcon: UIImage?, for state: UIControlState, type: buttonType) {
118+
switch type {
119+
case .left:
120+
setLeft(buttonIcon: buttonIcon, for: state)
121+
break
122+
case .right:
123+
setRight(buttonIcon: buttonIcon, for: state)
124+
break
125+
}
97126
buttonLayoutDidChange()
98127
}
99128

100-
public func set(buttonTitle: String, for state: UIControlState) {
101-
button.setTitle(buttonTitle, for: state)
129+
public func set(buttonTitle: String, for state: UIControlState, type: buttonType) {
130+
switch type {
131+
case .left:
132+
setLeft(buttonTitle: buttonTitle, for: state)
133+
break
134+
case .right:
135+
setRight(buttonTitle: buttonTitle, for: state)
136+
break
137+
}
102138
buttonLayoutDidChange()
103139
}
104140

105-
public var buttonTint: UIColor {
106-
get { return button.tintColor }
141+
private func setLeft(buttonIcon: UIImage?, for state: UIControlState) {
142+
leftButton.setImage(buttonIcon, for: state)
143+
}
144+
145+
private func setLeft(buttonTitle: String, for state: UIControlState) {
146+
leftButton.setTitle(buttonTitle, for: state)
147+
}
148+
149+
private func setRight(buttonIcon: UIImage?, for state: UIControlState) {
150+
rightButton.setImage(buttonIcon, for: state)
151+
}
152+
153+
private func setRight(buttonTitle: String, for state: UIControlState) {
154+
rightButton.setTitle(buttonTitle, for: state)
155+
}
156+
157+
public var leftButtonTint: UIColor {
158+
get { return leftButton.tintColor }
159+
set {
160+
leftButton.tintColor = newValue
161+
leftButton.setTitleColor(newValue, for: .normal)
162+
leftButton.imageView?.tintColor = newValue
163+
}
164+
}
165+
public var rightButtonTint: UIColor {
166+
get { return rightButton.tintColor }
107167
set {
108-
button.tintColor = newValue
109-
button.setTitleColor(newValue, for: .normal)
110-
button.imageView?.tintColor = newValue
168+
rightButton.tintColor = newValue
169+
rightButton.setTitleColor(newValue, for: .normal)
170+
rightButton.imageView?.tintColor = newValue
111171
}
112172
}
113173

@@ -131,13 +191,21 @@ public final class MessageView: UIView, MessageTextViewListener {
131191
set { textView.keyboardType = newValue }
132192
}
133193

134-
public func addButton(target: Any, action: Selector) {
135-
button.addTarget(target, action: action, for: .touchUpInside)
136-
buttonAction = action
194+
public func addButton(target: Any, action: Selector, type: buttonType) {
195+
switch type {
196+
case .left:
197+
leftButton.addTarget(target, action: action, for: .touchUpInside)
198+
leftButtonAction = action
199+
break
200+
case .right:
201+
rightButton.addTarget(target, action: action, for: .touchUpInside)
202+
rightButtonAction = action
203+
break
204+
}
137205
}
138206

139207
public override var keyCommands: [UIKeyCommand]? {
140-
guard let action = buttonAction else { return nil }
208+
guard let action = rightButtonAction else { return nil }
141209
return [UIKeyCommand(input: "\r", modifierFlags: .command, action: action)]
142210
}
143211

@@ -161,23 +229,35 @@ public final class MessageView: UIView, MessageTextViewListener {
161229
)
162230
let insetBounds = UIEdgeInsetsInsetRect(safeBounds, inset)
163231

164-
let buttonSize = button.bounds.size
165-
166-
let textViewFrame = CGRect(
232+
let size = textView.font?.lineHeight ?? 25 //Use textView line height
233+
let leftButtonSize = CGSize(width: size, height: size)
234+
let rightButtonSize = rightButton.bounds.size
235+
236+
// adjust by bottom offset so content is flush w/ text view
237+
let leftButtonFrame = CGRect(
167238
x: insetBounds.minX,
239+
y: (insetBounds.minY + textViewHeight) - leftButtonSize.height + leftButton.bottomHeightOffset,
240+
width: leftButtonSize.width,
241+
height: leftButtonSize.height
242+
)
243+
leftButton.frame = (showLeftButton) ? leftButtonFrame : .zero
244+
245+
let textViewFrame = CGRect(
246+
x: ((showLeftButton) ? leftButtonFrame.maxX : 0) + buttonLeftInset,
168247
y: insetBounds.minY,
169-
width: insetBounds.width - buttonSize.width - buttonLeftInset,
248+
width: insetBounds.width - ((showLeftButton) ? leftButtonSize.width : 0) - buttonLeftInset - rightButtonSize.width,
170249
height: textViewHeight
171250
)
172251
textView.frame = textViewFrame
173252

174253
// adjust by bottom offset so content is flush w/ text view
175-
button.frame = CGRect(
254+
let rightButtonFrame = CGRect(
176255
x: textViewFrame.maxX + buttonLeftInset,
177-
y: textViewFrame.maxY - buttonSize.height + button.bottomHeightOffset,
178-
width: buttonSize.width,
179-
height: buttonSize.height
256+
y: textViewFrame.maxY - rightButtonSize.height + rightButton.bottomHeightOffset,
257+
width: rightButtonSize.width,
258+
height: rightButtonSize.height
180259
)
260+
rightButton.frame = rightButtonFrame
181261

182262
let contentY = textViewFrame.maxY + inset.bottom
183263
contentView?.frame = CGRect(
@@ -217,12 +297,13 @@ public final class MessageView: UIView, MessageTextViewListener {
217297

218298
internal func updateEmptyTextStates() {
219299
let isEmpty = text.isEmpty
220-
button.isEnabled = !isEmpty
221-
button.alpha = isEmpty ? 0.25 : 1
300+
rightButton.isEnabled = !isEmpty
301+
rightButton.alpha = isEmpty ? 0.25 : 1
222302
}
223303

224304
internal func buttonLayoutDidChange() {
225-
button.sizeToFit()
305+
leftButton.sizeToFit()
306+
rightButton.sizeToFit()
226307
setNeedsLayout()
227308
}
228309

0 commit comments

Comments
 (0)