Skip to content

Commit 0f7fd23

Browse files
Merge pull request #51 from componentskit/fix/modal-keyboard-interaction
adapt modal position when a keyboard appears / disappears
2 parents 44350ca + 41b7721 commit 0f7fd23

File tree

5 files changed

+51
-9
lines changed

5 files changed

+51
-9
lines changed

Examples/DemosApp/DemosApp/ComponentsPreview/Helpers/ModalPreview+Helpers.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,6 +194,7 @@ Enim habitant laoreet inceptos scelerisque senectus, tellus molestie ut. Eros ri
194194
HStack {
195195
Text(self.headerTitle)
196196
.font(self.headerFont.font)
197+
Spacer()
197198
}
198199
} else {
199200
EmptyView()
@@ -211,6 +212,7 @@ Enim habitant laoreet inceptos scelerisque senectus, tellus molestie ut. Eros ri
211212
}
212213
}
213214
.font(self.bodyFont.font)
215+
.multilineTextAlignment(.leading)
214216
}
215217

216218
static func suFooter(

Sources/ComponentsKit/Components/Modal/SwiftUI/ModalContent.swift

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@ struct ModalContent<VM: ModalVM, Header: View, Body: View, Footer: View>: View {
2424
}
2525

2626
var body: some View {
27-
VStack(
28-
alignment: .leading,
29-
spacing: self.model.contentSpacing
30-
) {
27+
VStack(spacing: self.model.contentSpacing) {
3128
self.contentHeader()
3229
.observeSize {
3330
self.headerSize = $0

Sources/ComponentsKit/Components/Modal/UIKit/UKBottomModalController.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public class UKBottomModalController: UKModalController<BottomModalVM> {
9595
public override func layout() {
9696
super.layout()
9797

98-
self.contentView.bottom(self.model.outerPaddings.bottom, safeArea: true)
98+
self.contentViewBottomConstraint = self.contentView.bottom(self.model.outerPaddings.bottom, safeArea: true).bottom
9999
}
100100

101101
// MARK: - UIViewController Methods

Sources/ComponentsKit/Components/Modal/UIKit/UKCenterModalController.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,15 @@ public class UKCenterModalController: UKModalController<CenterModalVM> {
8888
public override func layout() {
8989
super.layout()
9090

91-
self.contentView.bottomAnchor.constraint(
91+
self.contentViewBottomConstraint = self.contentView.bottomAnchor.constraint(
9292
lessThanOrEqualTo: self.view.safeAreaLayoutGuide.bottomAnchor,
9393
constant: -self.model.outerPaddings.bottom
94-
).isActive = true
95-
self.contentView.centerVertically()
94+
)
95+
self.contentViewBottomConstraint?.isActive = true
96+
97+
let verticalConstraint = self.contentView.centerYAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.centerYAnchor)
98+
verticalConstraint.isActive = true
99+
verticalConstraint.priority = .defaultLow
96100
}
97101

98102
// MARK: - UIViewController Methods

Sources/ComponentsKit/Components/Modal/UIKit/UKModalController.swift

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ open class UKModalController<VM: ModalVM>: UIViewController {
1515
public let model: VM
1616

1717
private var contentViewWidthConstraint: NSLayoutConstraint?
18+
var contentViewBottomConstraint: NSLayoutConstraint?
1819

1920
// MARK: - Subviews
2021

@@ -53,6 +54,12 @@ open class UKModalController<VM: ModalVM>: UIViewController {
5354
fatalError("init(coder:) has not been implemented")
5455
}
5556

57+
// MARK: Deinitialization
58+
59+
deinit {
60+
NotificationCenter.default.removeObserver(self)
61+
}
62+
5663
// MARK: - Lifecycle
5764

5865
open override func viewDidLoad() {
@@ -65,7 +72,7 @@ open class UKModalController<VM: ModalVM>: UIViewController {
6572

6673
// MARK: - Setup
6774

68-
/// Sets up the modal's subviews and gesture recognizers.
75+
/// Sets up the modal's subviews, gesture recognizers and observers.
6976
open func setup() {
7077
self.view.addSubview(self.overlay)
7178
self.view.addSubview(self.contentView)
@@ -89,13 +96,45 @@ open class UKModalController<VM: ModalVM>: UIViewController {
8996
controller.handleTraitChanges()
9097
}
9198
}
99+
100+
NotificationCenter.default.addObserver(
101+
self,
102+
selector: #selector(self.handleKeyboardWillShow),
103+
name: UIResponder.keyboardWillShowNotification,
104+
object: nil
105+
)
106+
107+
NotificationCenter.default.addObserver(
108+
self,
109+
selector: #selector(self.handleKeyboardWillHide),
110+
name: UIResponder.keyboardWillHideNotification,
111+
object: nil
112+
)
92113
}
93114

94115
@objc func handleOverlayTap() {
95116
guard self.model.closesOnOverlayTap else { return }
96117
self.dismiss(animated: true)
97118
}
98119

120+
@objc func handleKeyboardWillShow(notification: NSNotification) {
121+
if let keyboardHeight = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue.height {
122+
let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? CGFloat ?? 0.25
123+
UIView.animate(withDuration: duration) {
124+
self.contentViewBottomConstraint?.constant = -keyboardHeight - self.model.contentPaddings.bottom + self.view.safeAreaInsets.bottom
125+
self.view.layoutIfNeeded()
126+
}
127+
}
128+
}
129+
130+
@objc func handleKeyboardWillHide(notification: NSNotification) {
131+
let duration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? CGFloat ?? 0.25
132+
UIView.animate(withDuration: duration) {
133+
self.contentViewBottomConstraint?.constant = -self.model.contentPaddings.bottom
134+
self.view.layoutIfNeeded()
135+
}
136+
}
137+
99138
// MARK: - Style
100139

101140
/// Applies styling to the modal's subviews.

0 commit comments

Comments
 (0)