| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- //
- // EmojiInputController.swift
- // LoopKit
- //
- // Copyright © 2017 LoopKit Authors. All rights reserved.
- //
- import UIKit
- public class EmojiInputController: UIInputViewController, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout, IdentifiableClass {
- @IBOutlet private weak var collectionView: UICollectionView!
- @IBOutlet private weak var sectionIndex: UIStackView!
- public weak var delegate: EmojiInputControllerDelegate?
- var emojis: EmojiDataSource!
- static func instance(withEmojis emojis: EmojiDataSource) -> EmojiInputController {
- let bundle = Bundle(for: self)
- let storyboard = UIStoryboard(name: className, bundle: bundle)
- let controller = storyboard.instantiateInitialViewController() as! EmojiInputController
- controller.emojis = emojis
- return controller
- }
- public override func viewDidLoad() {
- super.viewDidLoad()
- inputView = view as? UIInputView
- inputView?.allowsSelfSizing = true
- view.translatesAutoresizingMaskIntoConstraints = false
- if let layout = collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
- layout.sectionHeadersPinToVisibleBounds = true
- layout.sectionFootersPinToVisibleBounds = true
- }
- setupSectionIndex()
- // Scroll to medium absorption
- DispatchQueue.main.async {
- self.collectionView.scrollToItem(at: IndexPath(row: 0, section: 1), at: .left, animated: false)
- }
- }
- private func setupSectionIndex() {
- sectionIndex.removeAllArrangedSubviews()
- for section in emojis.sections {
- let label = UILabel(frame: .zero)
- label.text = section.indexSymbol
- sectionIndex.addArrangedSubview(label)
- }
- }
- @IBOutlet weak var deleteButton: UIButton! {
- didSet {
- let image = UIImage(systemName: "delete.left", compatibleWith: traitCollection)
- deleteButton.setImage(image, for: .normal)
- }
- }
- // MARK: - Actions
- @IBAction func switchKeyboard(_ sender: Any) {
- delegate?.emojiInputControllerDidAdvanceToStandardInputMode(self)
- }
- @IBAction func deleteBackward(_ sender: Any) {
- inputView?.playInputClick()
- textDocumentProxy.deleteBackward()
- }
- @IBAction func indexTouched(_ sender: UIGestureRecognizer) {
- let xLocation = max(0, sender.location(in: sectionIndex).x / sectionIndex.frame.width)
- let items = sectionIndex.arrangedSubviews.count
- let section = min(items - 1, Int(xLocation * CGFloat(items)))
- collectionView.scrollToItem(at: IndexPath(item: 0, section: section), at: .left, animated: false)
- }
- // MARK: - UICollectionViewDataSource
- public func numberOfSections(in collectionView: UICollectionView) -> Int {
- return emojis.sections.count
- }
- public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
- return emojis.sections[section].items.count
- }
- public func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
- let cell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: kind == UICollectionView.elementKindSectionHeader ? EmojiInputHeaderView.className : "Footer", for: indexPath)
- if let cell = cell as? EmojiInputHeaderView {
- cell.titleLabel.text = emojis.sections[indexPath.section].title.localizedUppercase
- }
- return cell
- }
- public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
- let cell = collectionView.dequeueReusableCell(withReuseIdentifier: EmojiInputCell.className, for: indexPath) as! EmojiInputCell
- cell.label.text = emojis.sections[indexPath.section].items[indexPath.row]
- return cell
- }
- // MARK: - UICollectionViewDelegateFlowLayout
- // MARK: - UICollectionViewDelegate
- public func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
- collectionView.deselectItem(at: indexPath, animated: true)
- inputView?.playInputClick()
- textDocumentProxy.insertText(emojis.sections[indexPath.section].items[indexPath.row])
- delegate?.emojiInputControllerDidSelectItemInSection(indexPath.section)
- }
- }
- public protocol EmojiInputControllerDelegate: AnyObject {
- func emojiInputControllerDidAdvanceToStandardInputMode(_ controller: EmojiInputController)
- func emojiInputControllerDidSelectItemInSection(_ section: Int)
- }
- // MARK: - Default Implementations
- extension EmojiInputControllerDelegate {
- public func emojiInputControllerDidSelectItemInSection(_ section: Int) { }
- }
- extension UIInputView: UIInputViewAudioFeedback {
- public var enableInputClicksWhenVisible: Bool { return true }
- func playInputClick() {
- let device = UIDevice.current
- device.playInputClick()
- }
- }
- private extension UIStackView {
- func removeAllArrangedSubviews() {
- for view in arrangedSubviews {
- view.removeFromSuperview()
- }
- }
- }
|