diff --git a/Examples/Examples/Assets.xcassets/AppIcon.appiconset/Contents.json b/Examples/Examples/Assets.xcassets/AppIcon.appiconset/Contents.json index 1d060ed..d8db8d6 100644 --- a/Examples/Examples/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/Examples/Examples/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -84,6 +84,11 @@ "idiom" : "ipad", "size" : "83.5x83.5", "scale" : "2x" + }, + { + "idiom" : "ios-marketing", + "size" : "1024x1024", + "scale" : "1x" } ], "info" : { diff --git a/Examples/Examples/Assets.xcassets/Contents.json b/Examples/Examples/Assets.xcassets/Contents.json new file mode 100644 index 0000000..da4a164 --- /dev/null +++ b/Examples/Examples/Assets.xcassets/Contents.json @@ -0,0 +1,6 @@ +{ + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Examples/Examples/Assets.xcassets/attachment.imageset/Contents.json b/Examples/Examples/Assets.xcassets/attachment.imageset/Contents.json new file mode 100644 index 0000000..854865a --- /dev/null +++ b/Examples/Examples/Assets.xcassets/attachment.imageset/Contents.json @@ -0,0 +1,22 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "attachment.png", + "scale" : "1x" + }, + { + "idiom" : "universal", + "filename" : "attachment@2x.png", + "scale" : "2x" + }, + { + "idiom" : "universal", + "scale" : "3x" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/Examples/Examples/Assets.xcassets/attachment.imageset/attachment.png b/Examples/Examples/Assets.xcassets/attachment.imageset/attachment.png new file mode 100644 index 0000000..451b4d7 Binary files /dev/null and b/Examples/Examples/Assets.xcassets/attachment.imageset/attachment.png differ diff --git a/Examples/Examples/Assets.xcassets/attachment.imageset/attachment@2x.png b/Examples/Examples/Assets.xcassets/attachment.imageset/attachment@2x.png new file mode 100644 index 0000000..753fd95 Binary files /dev/null and b/Examples/Examples/Assets.xcassets/attachment.imageset/attachment@2x.png differ diff --git a/Examples/Examples/ViewController.swift b/Examples/Examples/ViewController.swift index 1b343dd..050864d 100644 --- a/Examples/Examples/ViewController.swift +++ b/Examples/Examples/ViewController.swift @@ -25,14 +25,21 @@ class ViewController: MessageViewController, UITableViewDataSource, UITableViewD borderColor = .lightGray - messageView.inset = UIEdgeInsets(top: 8, left: 16, bottom: 8, right: 16) + messageView.inset = UIEdgeInsets(top: 8, left: 8, bottom: 8, right: 16) + messageView.font = UIFont.preferredFont(forTextStyle: .body) + messageView.buttonLeftInset = 8 + + messageView.set(buttonIcon: UIImage(named: "attachment"), for: .normal, type: .left) + messageView.addButton(target: self, action: #selector(onLeftButton), type: .left) + messageView.showLeftButton = true + messageView.textView.placeholderText = "New message..." messageView.textView.placeholderTextColor = .lightGray - messageView.font = UIFont.systemFont(ofSize: 17) + messageView.textView.backgroundColor = .white - messageView.set(buttonTitle: "Send", for: .normal) - messageView.addButton(target: self, action: #selector(onButton)) - messageView.buttonTint = .blue + messageView.set(buttonTitle: "Send", for: .normal, type: .right) + messageView.addButton(target: self, action: #selector(onRightButton), type: .right) + messageView.rightButtonTint = .blue messageAutocompleteController.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") messageAutocompleteController.tableView.dataSource = self @@ -52,7 +59,11 @@ class ViewController: MessageViewController, UITableViewDataSource, UITableViewD setup(scrollView: tableView) } - @objc func onButton() { + @objc func onLeftButton() { + print("Did press left button") + } + + @objc func onRightButton() { data.append(messageView.text) messageView.text = "" tableView.reloadData() diff --git a/MessageViewController/MessageView.swift b/MessageViewController/MessageView.swift index f8d458a..481f1a2 100644 --- a/MessageViewController/MessageView.swift +++ b/MessageViewController/MessageView.swift @@ -13,27 +13,44 @@ public final class MessageView: UIView, MessageTextViewListener { public let textView = MessageTextView() internal weak var delegate: MessageViewDelegate? - internal let button = UIButton() + internal let leftButton = UIButton() + internal let rightButton = UIButton() internal let UITextViewContentSizeKeyPath = #keyPath(UITextView.contentSize) internal let topBorderLayer = CALayer() internal var contentView: UIView? - internal var buttonAction: Selector? + internal var leftButtonAction: Selector? + internal var rightButtonAction: Selector? + public var showLeftButton: Bool = true + + public enum buttonType { + case left + case right + } internal override init(frame: CGRect) { super.init(frame: frame) backgroundColor = .white + addSubview(leftButton) addSubview(textView) - addSubview(button) + addSubview(rightButton) layer.addSublayer(topBorderLayer) + //Set action button + leftButton.imageEdgeInsets = .zero + leftButton.titleEdgeInsets = .zero + leftButton.contentEdgeInsets = .zero + leftButton.titleLabel?.font = self.font ?? UIFont.systemFont(ofSize: 14) + leftButton.imageView?.contentMode = .scaleAspectFit + leftButton.imageView?.clipsToBounds = true + // setup text view textView.contentInset = .zero textView.textContainerInset = .zero textView.backgroundColor = .clear textView.addObserver(self, forKeyPath: UITextViewContentSizeKeyPath, options: [.new], context: nil) - textView.font = .systemFont(ofSize: UIFont.systemFontSize) + textView.font = self.font ?? UIFont.systemFont(ofSize: 14) textView.add(listener: self) // setup TextKit props to defaults @@ -47,9 +64,12 @@ public final class MessageView: UIView, MessageTextViewListener { textView.layoutManager.usesFontLeading = true // setup send button - button.titleEdgeInsets = .zero - button.contentEdgeInsets = .zero - button.imageEdgeInsets = .zero + rightButton.imageEdgeInsets = .zero + rightButton.titleEdgeInsets = .zero + rightButton.contentEdgeInsets = .zero + rightButton.titleLabel?.font = self.font ?? UIFont.systemFont(ofSize: 14) + rightButton.imageView?.contentMode = .scaleAspectFit + rightButton.imageView?.clipsToBounds = true updateEmptyTextStates() } @@ -67,6 +87,8 @@ public final class MessageView: UIView, MessageTextViewListener { public var font: UIFont? { get { return textView.font } set { + leftButton.titleLabel?.font = newValue + rightButton.titleLabel?.font = newValue textView.font = newValue delegate?.wantsLayout(messageView: self) } @@ -92,22 +114,60 @@ public final class MessageView: UIView, MessageTextViewListener { didSet { setNeedsLayout() } } - public func set(buttonIcon: UIImage?, for state: UIControlState) { - button.setImage(buttonIcon, for: state) + public func set(buttonIcon: UIImage?, for state: UIControlState, type: buttonType) { + switch type { + case .left: + setLeft(buttonIcon: buttonIcon, for: state) + break + case .right: + setRight(buttonIcon: buttonIcon, for: state) + break + } buttonLayoutDidChange() } - public func set(buttonTitle: String, for state: UIControlState) { - button.setTitle(buttonTitle, for: state) + public func set(buttonTitle: String, for state: UIControlState, type: buttonType) { + switch type { + case .left: + setLeft(buttonTitle: buttonTitle, for: state) + break + case .right: + setRight(buttonTitle: buttonTitle, for: state) + break + } buttonLayoutDidChange() } - public var buttonTint: UIColor { - get { return button.tintColor } + private func setLeft(buttonIcon: UIImage?, for state: UIControlState) { + leftButton.setImage(buttonIcon, for: state) + } + + private func setLeft(buttonTitle: String, for state: UIControlState) { + leftButton.setTitle(buttonTitle, for: state) + } + + private func setRight(buttonIcon: UIImage?, for state: UIControlState) { + rightButton.setImage(buttonIcon, for: state) + } + + private func setRight(buttonTitle: String, for state: UIControlState) { + rightButton.setTitle(buttonTitle, for: state) + } + + public var leftButtonTint: UIColor { + get { return leftButton.tintColor } + set { + leftButton.tintColor = newValue + leftButton.setTitleColor(newValue, for: .normal) + leftButton.imageView?.tintColor = newValue + } + } + public var rightButtonTint: UIColor { + get { return rightButton.tintColor } set { - button.tintColor = newValue - button.setTitleColor(newValue, for: .normal) - button.imageView?.tintColor = newValue + rightButton.tintColor = newValue + rightButton.setTitleColor(newValue, for: .normal) + rightButton.imageView?.tintColor = newValue } } @@ -131,13 +191,21 @@ public final class MessageView: UIView, MessageTextViewListener { set { textView.keyboardType = newValue } } - public func addButton(target: Any, action: Selector) { - button.addTarget(target, action: action, for: .touchUpInside) - buttonAction = action + public func addButton(target: Any, action: Selector, type: buttonType) { + switch type { + case .left: + leftButton.addTarget(target, action: action, for: .touchUpInside) + leftButtonAction = action + break + case .right: + rightButton.addTarget(target, action: action, for: .touchUpInside) + rightButtonAction = action + break + } } public override var keyCommands: [UIKeyCommand]? { - guard let action = buttonAction else { return nil } + guard let action = rightButtonAction else { return nil } return [UIKeyCommand(input: "\r", modifierFlags: .command, action: action)] } @@ -161,23 +229,35 @@ public final class MessageView: UIView, MessageTextViewListener { ) let insetBounds = UIEdgeInsetsInsetRect(safeBounds, inset) - let buttonSize = button.bounds.size - - let textViewFrame = CGRect( + let size = textView.font?.lineHeight ?? 25 //Use textView line height + let leftButtonSize = CGSize(width: size, height: size) + let rightButtonSize = rightButton.bounds.size + + // adjust by bottom offset so content is flush w/ text view + let leftButtonFrame = CGRect( x: insetBounds.minX, + y: (insetBounds.minY + textViewHeight) - leftButtonSize.height + leftButton.bottomHeightOffset, + width: leftButtonSize.width, + height: leftButtonSize.height + ) + leftButton.frame = (showLeftButton) ? leftButtonFrame : .zero + + let textViewFrame = CGRect( + x: ((showLeftButton) ? leftButtonFrame.maxX : 0) + buttonLeftInset, y: insetBounds.minY, - width: insetBounds.width - buttonSize.width - buttonLeftInset, + width: insetBounds.width - ((showLeftButton) ? leftButtonSize.width : 0) - buttonLeftInset - rightButtonSize.width, height: textViewHeight ) textView.frame = textViewFrame // adjust by bottom offset so content is flush w/ text view - button.frame = CGRect( + let rightButtonFrame = CGRect( x: textViewFrame.maxX + buttonLeftInset, - y: textViewFrame.maxY - buttonSize.height + button.bottomHeightOffset, - width: buttonSize.width, - height: buttonSize.height + y: textViewFrame.maxY - rightButtonSize.height + rightButton.bottomHeightOffset, + width: rightButtonSize.width, + height: rightButtonSize.height ) + rightButton.frame = rightButtonFrame let contentY = textViewFrame.maxY + inset.bottom contentView?.frame = CGRect( @@ -217,12 +297,13 @@ public final class MessageView: UIView, MessageTextViewListener { internal func updateEmptyTextStates() { let isEmpty = text.isEmpty - button.isEnabled = !isEmpty - button.alpha = isEmpty ? 0.25 : 1 + rightButton.isEnabled = !isEmpty + rightButton.alpha = isEmpty ? 0.25 : 1 } internal func buttonLayoutDidChange() { - button.sizeToFit() + leftButton.sizeToFit() + rightButton.sizeToFit() setNeedsLayout() }