-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathKeyboardAvoidingView.swift
88 lines (70 loc) · 2.91 KB
/
KeyboardAvoidingView.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
import ExpoModulesCore
// This view will be used as a native component. Make sure to inherit from `ExpoView`
// to apply the proper styling (e.g. border radius and shadows).
class KeyboardAvoidingView: ExpoView, ViewBoundsObserving {
private let measurer = BoundsObservableView()
private let container = UIView()
private var scrollViewComponent: ScrollViewComponentWrapper?
private var onKeyboardHeightChanged = EventDispatcher()
required init(appContext: AppContext? = nil) {
super.init(appContext: appContext)
clipsToBounds = true
measurer.translatesAutoresizingMaskIntoConstraints = false
measurer.isHidden = true
measurer.delegate = self
addSubview(measurer)
container.translatesAutoresizingMaskIntoConstraints = false
addSubview(container)
NSLayoutConstraint.activate([
measurer.leadingAnchor.constraint(equalTo: leadingAnchor),
measurer.trailingAnchor.constraint(equalTo: trailingAnchor),
measurer.bottomAnchor.constraint(equalTo: bottomAnchor),
])
NSLayoutConstraint.activate([
container.heightAnchor.constraint(equalTo: heightAnchor),
container.leadingAnchor.constraint(equalTo: leadingAnchor),
container.trailingAnchor.constraint(equalTo: trailingAnchor),
container.bottomAnchor.constraint(equalTo: bottomAnchor),
])
let measurerTopToKeyboard = measurer.topAnchor.constraint(
equalTo: keyboardLayoutGuide.topAnchor)
measurerTopToKeyboard.identifier = "measurerTopToKeyboard"
keyboardLayoutGuide.setConstraints(
[measurerTopToKeyboard], activeWhenNearEdge: .bottom)
let measurerTopToBottom = measurer.topAnchor.constraint(equalTo: bottomAnchor)
measurerTopToBottom.identifier = "measurerTopToKeyboard"
keyboardLayoutGuide.setConstraints(
[measurerTopToBottom], activeWhenAwayFrom: .bottom)
keyboardLayoutGuide.followsUndockedKeyboard = true
if #available(iOS 17.0, *) {
keyboardLayoutGuide.usesBottomSafeArea = false
}
}
func boundsDidChange(_ view: BoundsObservableView, from previousBounds: CGRect) {
let animation = view.layer.animation(forKey: "bounds.size")
onKeyboardHeightChanged(
["height": view.bounds.height,
"duration": (animation?.duration ?? 0) * 1000]
)
}
#if RCT_NEW_ARCH_ENABLED
override func mountChildComponentView(_ childComponentView: UIView, index: Int) {
container.insertSubview(childComponentView, at: index)
}
override func unmountChildComponentView(_ childComponentView: UIView, index: Int) {
childComponentView.removeFromSuperview()
}
#else
override func insertReactSubview(_ subview: UIView!, at index: Int) {
super.insertReactSubview(subview, at: index)
container.insertSubview(subview, at: index)
}
override func removeReactSubview(_ subview: UIView!) {
super.removeReactSubview(subview)
subview.removeFromSuperview()
}
override func didUpdateReactSubviews() {
// no-op
}
#endif
}