Skip to content

Commit

Permalink
0.7
Browse files Browse the repository at this point in the history
  • Loading branch information
xnth97 committed Jun 11, 2021
1 parent 0fcd831 commit d1305ab
Show file tree
Hide file tree
Showing 6 changed files with 92 additions and 62 deletions.
2 changes: 1 addition & 1 deletion AccessoryKit.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'AccessoryKit'
s.version = '0.6.1'
s.version = '0.7'
s.summary = 'A customizable, expandable, and easy-to-use input accessory view component for iOS.'

s.description = <<-DESC
Expand Down
26 changes: 13 additions & 13 deletions Example/AccessoryKit/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,22 +18,22 @@ class ViewController: UIViewController {
super.viewDidLoad()

let keyButtons: [KeyboardAccessoryButton] = [
KeyboardAccessoryButton(type: .tab, tapHandler: {}),
KeyboardAccessoryButton(type: .undo, tapHandler: { [weak self] in
KeyboardAccessoryButton(type: .tab),
KeyboardAccessoryButton(type: .undo) { [weak self] in
self?.undo()
}),
KeyboardAccessoryButton(type: .redo, tapHandler: { [weak self] in
},
KeyboardAccessoryButton(type: .redo) { [weak self] in
self?.redo()
}),
KeyboardAccessoryButton(type: .header, tapHandler: {}),
KeyboardAccessoryButton(type: .bold, tapHandler: {}),
KeyboardAccessoryButton(type: .italic, tapHandler: {}),
KeyboardAccessoryButton(type: .code, tapHandler: {}),
KeyboardAccessoryButton(type: .delete, tapHandler: {}),
KeyboardAccessoryButton(type: .item, tapHandler: {}),
KeyboardAccessoryButton(type: .quote, tapHandler: {}),
},
KeyboardAccessoryButton(type: .header),
KeyboardAccessoryButton(type: .bold),
KeyboardAccessoryButton(type: .italic),
KeyboardAccessoryButton(type: .code),
KeyboardAccessoryButton(type: .delete),
KeyboardAccessoryButton(type: .item),
KeyboardAccessoryButton(type: .quote),
KeyboardAccessoryButton(type: .link, menu: createInsertMenu()),
KeyboardAccessoryButton(type: .image, tapHandler: {}),
KeyboardAccessoryButton(type: .image),
KeyboardAccessoryButton(title: "Esc"),
]
accessoryView = KeyboardAccessoryView(
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ To run the example project, clone the repo, and run `pod install` from the Examp
// Create view model array of key buttons
let keyButtons: [KeyboardAccessoryButton] = [
// Create button with built-in type and tap handler block
KeyboardAccessoryButton(type: .undo, tapHandler: { [weak self] in
KeyboardAccessoryButton(type: .undo) { [weak self] in
self?.undo()
}),
},
// Create button with UIImage
KeyboardAccessoryButton(image: UIImage(named: "img"), tapHandler: {}),
// Create button with title
Expand Down
46 changes: 33 additions & 13 deletions Sources/AccessoryKit/KeyboardAccessoryButton.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import UIKit

/// View model struct that represents a key button inside `KeyboardAccessoryView`.
public struct KeyboardAccessoryButton {

/// Pre-defined types of key button.
public enum ButtonType {
case tab
Expand All @@ -25,7 +25,9 @@ public struct KeyboardAccessoryButton {
case link
case image
}


// MARK: - Constants

private static let imageNameMap: [ButtonType: String] = [
.tab: "increase.indent",
.undo: "arrow.uturn.left",
Expand All @@ -40,51 +42,69 @@ public struct KeyboardAccessoryButton {
.link: "link",
.image: "photo",
]


// MARK: - Properties

/// The image that is shown on the button.
public let image: UIImage?

/// The title that is shown on the button.
public let title: String?


/// The font of title label of button.
public let font: UIFont?

/// The tint color of button. Please note that this will be overriden if `KeyboardAccessoryView`
/// sets tint color.
public let tintColor: UIColor

/// The tap handler that will be invoked when tapping the button.
public let tapHandler: (() -> Void)?

/// The menu that will be shown once button is tapped.
public let menu: UIMenu?


// MARK: - Initializers

/// Initialize the view model of key button inside `KeyboardAccessoryView`.
/// - Parameters:
/// - title: The title that is shown on the button.
/// - font: The font of title label of button.
/// - image: The image that is shown on the button.
/// - tapHandler: The tap handler that will be invoked when tapping the button.
/// - tintColor: The tint color of button.
/// - menu: The menu that will be shown once button is tapped. Only available for iOS 14+.
/// - tapHandler: The tap handler that will be invoked when tapping the button.
public init(title: String? = nil,
font: UIFont? = nil,
image: UIImage? = nil,
tapHandler: (() -> Void)? = nil,
menu: UIMenu? = nil) {
tintColor: UIColor = .systemBlue,
menu: UIMenu? = nil,
tapHandler: (() -> Void)? = nil) {
if title == nil && image == nil {
fatalError("[AccessoryKit] Error: Must provide a title or an image for button.")
}
self.title = title
self.font = font
self.image = image
self.tapHandler = tapHandler
self.menu = menu
self.tintColor = tintColor
}

/// Initialize the view model of key button with a given button type.
/// - Parameters:
/// - type: Pre-defined button type.
/// - tapHandler: The tap handler that will be invoked when tapping the button.
/// - menu: The menu that will be shown once button is tapped. Only available for iOS 14+.
public init(type: ButtonType,
tapHandler: (() -> Void)? = nil,
menu: UIMenu? = nil) {
tintColor: UIColor = .systemBlue,
menu: UIMenu? = nil,
tapHandler: (() -> Void)? = nil) {
guard let imageName = Self.imageNameMap[type],
let image = UIImage(systemName: imageName) else {
fatalError("[AccessoryKit] Error: Do not have corresponding image for button type \(type)")
}
self.init(image: image, tapHandler: tapHandler, menu: menu)
self.init(image: image, tintColor: tintColor, menu: menu, tapHandler: tapHandler)
}

}
23 changes: 15 additions & 8 deletions Sources/AccessoryKit/KeyboardAccessoryButtonView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class KeyboardAccessoryButtonView: UIView {
private let button = UIButton(type: .custom)
private let viewModel: KeyboardAccessoryButton
private let viewSize: CGSize

init(viewModel: KeyboardAccessoryButton,
width: CGFloat,
height: CGFloat,
Expand All @@ -23,12 +23,19 @@ class KeyboardAccessoryButtonView: UIView {
super.init(frame: CGRect(x: 0, y: 0, width: width, height: height))

addSubview(button)

button.setImage(viewModel.image, for: .normal)
button.setTitle(viewModel.title, for: .normal)
button.setTitleColor(.systemBlue, for: .normal)

button.tintColor = viewModel.tintColor
button.setTitleColor(viewModel.tintColor, for: .normal)

if let font = viewModel.font {
button.titleLabel?.font = font
}

button.backgroundColor = .tertiarySystemGroupedBackground

button.clipsToBounds = true
button.layer.cornerRadius = cornerRadius
button.translatesAutoresizingMaskIntoConstraints = false
Expand All @@ -53,17 +60,17 @@ class KeyboardAccessoryButtonView: UIView {
button.addTarget(self, action: #selector(tapHandlerAction), for: .touchUpInside)
}
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

@objc private func tapHandlerAction() {
viewModel.tapHandler?()
}

// MARK: - APIs

override var intrinsicContentSize: CGSize {
return viewSize
}
Expand All @@ -83,5 +90,5 @@ class KeyboardAccessoryButtonView: UIView {
button.isEnabled
}
}

}
53 changes: 28 additions & 25 deletions Sources/AccessoryKit/KeyboardAccessoryView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,42 @@ import UIKit

/// Delegate for `KeyboardAccessoryView`.
@objc public protocol KeyboardAccessoryViewDelegate: AnyObject {

/// This function is called when `KeyboardAccessoryView` has `showDismissKeyboardKey` and the dismiss keyboard
/// key is tapped.
@objc optional func dismissKeyboardButtonTapped()

}

/// The `UIView` class that works as the `inputAccessoryView`, usually looks like a toolbar on top of the screen keyboard.
public class KeyboardAccessoryView: UIInputView {

/// Constants

// MARK: - Constants

public static let defaultKeyWidth: CGFloat = 60.0
public static let defaultKeyHeight: CGFloat = 40.0
public static let defaultKeyCornerRadius: CGFloat = 8.0
public static let defaultKeyMargin: CGFloat = 8.0

/// Properties

// MARK: - Properties

private let container = UIView()
private let keysScrollView = UIScrollView()
private let keysStackView = UIStackView()

private let keyMargin: CGFloat
private let keyWidth: CGFloat
private let keyHeight: CGFloat
private let keyCornerRadius: CGFloat
private let keyButtonViews: [KeyboardAccessoryButtonView]
private let showDismissKeyboardKey: Bool

public var accessoryViewHeight: CGFloat {
return 2 * keyMargin + keyHeight
}

private weak var delegate: KeyboardAccessoryViewDelegate?

/// Initializer of `KeyboardAccessoryView`
/// - Parameters:
/// - frame: The frame rectangle, which describes the view’s location and size in its superview’s coordinate system.
Expand Down Expand Up @@ -86,14 +89,14 @@ public class KeyboardAccessoryView: UIInputView {

autoresizingMask = .flexibleHeight
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

private func setupViews() {
var constraints: [NSLayoutConstraint] = []

addSubview(container)
container.translatesAutoresizingMaskIntoConstraints = false
constraints.append(contentsOf: [
Expand All @@ -103,7 +106,7 @@ public class KeyboardAccessoryView: UIInputView {
container.bottomAnchor.constraint(equalTo: safeAreaLayoutGuide.bottomAnchor),
container.heightAnchor.constraint(equalToConstant: accessoryViewHeight),
])

container.addSubview(keysScrollView)
keysScrollView.translatesAutoresizingMaskIntoConstraints = false
keysScrollView.alwaysBounceHorizontal = true
Expand All @@ -112,7 +115,7 @@ public class KeyboardAccessoryView: UIInputView {
keysScrollView.centerYAnchor.constraint(equalTo: container.centerYAnchor),
keysScrollView.heightAnchor.constraint(equalToConstant: keyHeight),
])

let keyboardDismissImage = UIImage(systemName: "keyboard.chevron.compact.down")
if let image = keyboardDismissImage, showDismissKeyboardKey {
let dismissKey = KeyboardAccessoryButton(image: image) { [weak self] in
Expand All @@ -134,7 +137,7 @@ public class KeyboardAccessoryView: UIInputView {
} else {
constraints.append(keysScrollView.trailingAnchor.constraint(equalTo: container.trailingAnchor))
}

keysScrollView.addSubview(keysStackView)
keysStackView.translatesAutoresizingMaskIntoConstraints = false
keysStackView.axis = .horizontal
Expand All @@ -144,34 +147,34 @@ public class KeyboardAccessoryView: UIInputView {
keysStackView.centerYAnchor.constraint(equalTo: keysScrollView.centerYAnchor),
keysStackView.heightAnchor.constraint(equalToConstant: keyHeight),
])

keyButtonViews.forEach {
addAccessoryKey(keyView: $0)
}

NSLayoutConstraint.activate(constraints)

keysStackView.layoutIfNeeded()
let stackViewSize = keysStackView.frame.size
keysScrollView.contentSize = CGSize(width: stackViewSize.width + keyMargin, height: stackViewSize.height)
keysScrollView.showsHorizontalScrollIndicator = false
keysScrollView.showsVerticalScrollIndicator = false
}

private func addAccessoryKey(keyView: UIView) {
keysStackView.addArrangedSubview(keyView)
}

private func dismissKeyboardKeyTapped() {
delegate?.dismissKeyboardButtonTapped?()
}

public override var intrinsicContentSize: CGSize {
return CGSize(width: UIView.noIntrinsicMetric, height: accessoryViewHeight)
}

// MARK: - APIs

/// Set `isEnabled` value on the key of a given index.
/// - Parameters:
/// - enabled: Boolean value indicating whether the key is enabled.
Expand All @@ -182,7 +185,7 @@ public class KeyboardAccessoryView: UIInputView {
}
keyButtonViews[index].isEnabled = enabled
}

/// Set `tintColor` value on the key of a given index.
/// - Parameters:
/// - tintColor: Tint color to be set.
Expand All @@ -206,5 +209,5 @@ public class KeyboardAccessoryView: UIInputView {
super.tintColor
}
}

}

0 comments on commit d1305ab

Please sign in to comment.