Skip to content

Commit

Permalink
feat: additionalInputViewBottomConstraintConstant in KeyboardManager
Browse files Browse the repository at this point in the history
  • Loading branch information
martinpucik committed May 16, 2022
1 parent d82d046 commit bc80b17
Show file tree
Hide file tree
Showing 9 changed files with 185 additions and 101 deletions.
24 changes: 18 additions & 6 deletions Example/Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
131A72ED28325D2E001F73BE /* AdditionalBottomSpaceExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 131A72EC28325D2E001F73BE /* AdditionalBottomSpaceExampleViewController.swift */; };
3821ADE120F534DA00DE0D1D /* SubviewExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3821ADDF20F534DA00DE0D1D /* SubviewExampleViewController.swift */; };
3821ADE220F534DA00DE0D1D /* InputAccessoryExampleViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3821ADE020F534DA00DE0D1D /* InputAccessoryExampleViewController.swift */; };
3821ADE420F5359800DE0D1D /* CommonTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3821ADE320F5359800DE0D1D /* CommonTableViewController.swift */; };
Expand Down Expand Up @@ -45,6 +46,7 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
131A72EC28325D2E001F73BE /* AdditionalBottomSpaceExampleViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdditionalBottomSpaceExampleViewController.swift; sourceTree = "<group>"; };
3821ADDF20F534DA00DE0D1D /* SubviewExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SubviewExampleViewController.swift; sourceTree = "<group>"; };
3821ADE020F534DA00DE0D1D /* InputAccessoryExampleViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = InputAccessoryExampleViewController.swift; sourceTree = "<group>"; };
3821ADE320F5359800DE0D1D /* CommonTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonTableViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -83,6 +85,19 @@
/* End PBXFrameworksBuildPhase section */

/* Begin PBXGroup section */
131A72EB28325A05001F73BE /* Example ViewControllers */ = {
isa = PBXGroup;
children = (
3821ADE320F5359800DE0D1D /* CommonTableViewController.swift */,
38FCF9D5219F797600A47350 /* READMEPreviewViewController.swift */,
3821ADE020F534DA00DE0D1D /* InputAccessoryExampleViewController.swift */,
3821ADDF20F534DA00DE0D1D /* SubviewExampleViewController.swift */,
131A72EC28325D2E001F73BE /* AdditionalBottomSpaceExampleViewController.swift */,
46E4094D252996D900D238A8 /* SwiftUIExample.swift */,
);
path = "Example ViewControllers";
sourceTree = "<group>";
};
383B83901F47897800027965 = {
isa = PBXGroup;
children = (
Expand All @@ -106,14 +121,10 @@
isa = PBXGroup;
children = (
383B839C1F47897800027965 /* AppDelegate.swift */,
38FCF9D5219F797600A47350 /* READMEPreviewViewController.swift */,
388714E8202AC9620064C8BB /* InputBarStyleSelectionController.swift */,
3821ADE320F5359800DE0D1D /* CommonTableViewController.swift */,
3821ADE020F534DA00DE0D1D /* InputAccessoryExampleViewController.swift */,
3821ADDF20F534DA00DE0D1D /* SubviewExampleViewController.swift */,
46E4094D252996D900D238A8 /* SwiftUIExample.swift */,
468A8726251C8AAB0018D007 /* Community Examples */,
131A72EB28325A05001F73BE /* Example ViewControllers */,
38F0C1FC20C89C8700FF8DD3 /* InputBar Examples */,
468A8726251C8AAB0018D007 /* Community Examples */,
38F0C20920C89D2D00FF8DD3 /* Cells */,
38F0C20A20C89D4100FF8DD3 /* Sample Data */,
);
Expand Down Expand Up @@ -266,6 +277,7 @@
383989BD1F564F5C003D30DD /* Random.swift in Sources */,
388714EB202AC9A50064C8BB /* SampleData.swift in Sources */,
38F0C20020C89CA200FF8DD3 /* SlackInputBar.swift in Sources */,
131A72ED28325D2E001F73BE /* AdditionalBottomSpaceExampleViewController.swift in Sources */,
388714E9202AC9620064C8BB /* InputBarStyleSelectionController.swift in Sources */,
383989BA1F55C600003D30DD /* Lorem.swift in Sources */,
3821ADE120F534DA00DE0D1D /* SubviewExampleViewController.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
//
// AdditionalBottomSpaceExampleViewController.swift
// Example
//
// Created by Martin Púčik on 16.05.2022.
// Copyright © 2022 Nathan Tannar. All rights reserved.
//

import Foundation
import UIKit
import InputBarAccessoryView

final class AdditionalBottomSpaceExampleViewController: CommonTableViewController {

private lazy var keyboardManager = KeyboardManager()

private lazy var additionalBottomBar: UIView = {
let view = UIView()
view.backgroundColor = .systemBlue
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()

override func viewDidLoad() {
super.viewDidLoad()

view.addSubview(inputBar)
view.addSubview(additionalBottomBar)

NSLayoutConstraint.activate([
additionalBottomBar.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
additionalBottomBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
additionalBottomBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
additionalBottomBar.heightAnchor.constraint(equalToConstant: 50)
])

view.layoutIfNeeded()

keyboardManager.additionalInputViewBottomConstraintConstant = {
var safeBottomInset: CGFloat = self.view.safeAreaInsets.bottom
if let windowBottomInset = UIApplication.shared.windows.first?.safeAreaInsets.bottom,
safeBottomInset != windowBottomInset {
safeBottomInset = windowBottomInset
}
return -(self.additionalBottomBar.frame.height + safeBottomInset)
}

// Binding the inputBar will set the needed callback actions to position the inputBar on top of the keyboard
keyboardManager.bind(inputAccessoryView: inputBar)

// Binding to the tableView will enabled interactive dismissal
keyboardManager.bind(to: tableView)
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)

/// This replicates instagram's behavior when commenting in a post. As of 2020-09, it appears like they have one of the best product experiences of this handling the keyboard when dismissing the UIViewController
self.inputBar.inputTextView.resignFirstResponder()
/// This is set because otherwise, if only partially dragging the left edge of the screen, and then cancelling the dismissal, on viewDidAppear UIKit appears to set the first responder back to the inputTextView (https://stackoverflow.com/a/41847448)
self.inputBar.inputTextView.canBecomeFirstResponder = false
}

override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

/// The opposite of `viewWillDisappear(_:)`
self.inputBar.inputTextView.canBecomeFirstResponder = true
self.inputBar.inputTextView.becomeFirstResponder()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,14 @@ final class SubviewExampleViewController: CommonTableViewController {
super.viewDidLoad()

view.addSubview(inputBar)


keyboardManager.shouldApplyAdditionBottomSpaceToInteractiveDismissal = true
// Binding the inputBar will set the needed callback actions to position the inputBar on top of the keyboard
keyboardManager.bind(inputAccessoryView: inputBar)
keyboardManager.bind(inputAccessoryView: inputBar, withAdditionalBottomSpace: {
return 0
return -self.view.safeAreaInsets.bottom
return -(self.inputBar.frame.height + self.view.safeAreaInsets.bottom)
})

// Binding to the tableView will enabled interactive dismissal
keyboardManager.bind(to: tableView)
Expand Down
File renamed without changes.
75 changes: 34 additions & 41 deletions Example/Sources/InputBarStyleSelectionController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,6 @@ class InputBarStyleSelectionController: UITableViewController {
tableView.tableFooterView = UIView()
title = "InputBarAccessoryView"
navigationItem.backBarButtonItem = UIBarButtonItem(title: "Styles", style: .plain, target: nil, action: nil)
if #available(iOS 13, *) {
navigationController?.navigationBar.tintColor = .systemBackground
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.systemBackground]
} else {
navigationController?.navigationBar.tintColor = .white
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor.white]
}
navigationController?.navigationBar.barTintColor = .systemBlue
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
Expand All @@ -49,7 +41,7 @@ class InputBarStyleSelectionController: UITableViewController {
switch section {
case 0: return 1
case 1...2: return styles.count
case 3: return 3
case 3: return 4
default: fatalError("unknown section \(section)")
}
}
Expand All @@ -60,8 +52,9 @@ class InputBarStyleSelectionController: UITableViewController {
case (0, _): cell.textLabel?.text = "README Preview"
case (1...2, _): cell.textLabel?.text = styles[indexPath.row].rawValue
case (3, 0): cell.textLabel?.text = "Tab bar example (Slack style)"
case (3, 1): cell.textLabel?.text = "Send button animations"
case (3, 2): cell.textLabel?.text = "SwiftUI example"
case (3, 1): cell.textLabel?.text = "Addition bottom space example (Slack)"
case (3, 2): cell.textLabel?.text = "Send button animations"
case (3, 3): cell.textLabel?.text = "SwiftUI example"
default: assertionFailure("unrecognized \(indexPath). Are you trying to add an additional example?")
}

Expand All @@ -70,38 +63,38 @@ class InputBarStyleSelectionController: UITableViewController {
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

if indexPath.section == 0 {
let convo = SampleData.shared.getConversations(count: 1)[0]
switch indexPath.section {
case 0:
navigationController?.pushViewController(READMEPreviewViewController(), animated: true)
} else {
let convo = SampleData.shared.getConversations(count: 1)[0]
if indexPath.section == 1 {
navigationController?.pushViewController(
InputAccessoryExampleViewController(style: styles[indexPath.row],
conversation: convo),
animated: true)
} else if indexPath.section == 2 {
navigationController?.pushViewController(
SubviewExampleViewController(style: styles[indexPath.row],
conversation: convo),
animated: true)
} else if indexPath.section == 3 {
switch indexPath.row {
case 0:
let tabBarController = UITabBarController()
let contained = SubviewExampleViewController(style: InputBarStyle.slack, conversation: convo)
tabBarController.viewControllers = [contained]
navigationController?.pushViewController(tabBarController, animated: true)
case 1:
let example = ButtonAnimationExample(style: .imessage, conversation: convo)
navigationController?.pushViewController(example, animated: true)
case 2:
let example = UIHostingController(rootView: SwiftUIExample.make(style: .imessage, conversation: convo))
navigationController?.pushViewController(example, animated: true)
default:
fatalError("Unknown row \(indexPath.row) in Community Examples section. Are you trying to add a new example?")
}
case 1:
let controller = InputAccessoryExampleViewController(style: styles[indexPath.row], conversation: convo)
navigationController?.pushViewController(controller, animated: true)
case 2:
let controller = SubviewExampleViewController(style: styles[indexPath.row], conversation: convo)
navigationController?.pushViewController(controller, animated: true)
case 3:
switch indexPath.row {
case 0:
let tabBarController = UITabBarController()
let contained = SubviewExampleViewController(style: InputBarStyle.slack, conversation: convo)
tabBarController.viewControllers = [contained]
contained.tabBarItem = UITabBarItem(title: "Slack", image: UIImage(systemName: "number"), tag: 0)
navigationController?.pushViewController(tabBarController, animated: true)
case 1:
let example = AdditionalBottomSpaceExampleViewController(style: .slack, conversation: convo)
navigationController?.pushViewController(example, animated: true)
case 2:
let example = ButtonAnimationExample(style: .imessage, conversation: convo)
navigationController?.pushViewController(example, animated: true)
case 3:
let example = UIHostingController(rootView: SwiftUIExample.make(style: .imessage, conversation: convo))
navigationController?.pushViewController(example, animated: true)
default:
fatalError("Unknown row \(indexPath.row) in Community Examples section. Are you trying to add a new example?")
}
default:
fatalError("Unknown Section \(indexPath.section). Are you trying to add a new example?")
}
}
}
Loading

0 comments on commit bc80b17

Please sign in to comment.