Skip to content

Commit

Permalink
fix: iOS 16 incorrect height in onEnd event
Browse files Browse the repository at this point in the history
  • Loading branch information
kirillzyusko committed Nov 12, 2024
1 parent b884cdb commit dd20a0c
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 5 deletions.
3 changes: 2 additions & 1 deletion TODO
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
- (x) close after interactive gesture - sudden jump of 75 pixels -> fixed by detaching iav during `onInteractive`
- (x) keyboard hidden -> remove inputAccessoryView - done in resignFirstResponder
- (x) iOS 16 - after attaching fake iav we dispatch onEnd with height - 248 (298 - 50) -> ignore events after attaching iav, because in keyboardDidAppear `position` can be a random value (291 or 341)
- show after interactive - keyboard height is 386
- iOS 16 - after attaching fake iav we dispatch onEnd with height - 248 (298 - 50)
- text input grow -> can not make interactive gesture (Optional(424.6666666666667) 424.66666666666674)
4 changes: 4 additions & 0 deletions ios/extensions/Notification.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,7 @@ extension Notification {
return (duration, keyboardFrame)
}
}

extension Notification.Name {
static let shouldIgnoreKeyboardEvents = Notification.Name("shouldIgnoreKeyboardEvents")
}
4 changes: 2 additions & 2 deletions ios/interactive/InvisibleInputAccessoryView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,8 @@ public class InvisibleInputAccessoryView: UIView {
private func setupView() {
isUserInteractionEnabled = false
// TODO: Set the background color to transparent
backgroundColor = UIColor.red
// self.backgroundColor = .clear
// backgroundColor = UIColor.red
backgroundColor = .clear
autoresizingMask = .flexibleHeight
}
}
4 changes: 4 additions & 0 deletions ios/interactive/KeyboardAreaExtender.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ class KeyboardAreaExtender: NSObject {

activeTextInput.inputAccessoryView = currentInputAccessoryView
activeTextInput.reloadInputViews()

NotificationCenter.default.post(name: .shouldIgnoreKeyboardEvents, object: nil, userInfo: ["ignore": true])

print("Attaching `inputAccessoryView` \(Date.currentTimeStamp)")
}
}
}
26 changes: 24 additions & 2 deletions ios/observers/KeyboardMovementObserver.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ public class KeyboardMovementObserver: NSObject {
private var tag: NSNumber = -1
private var animation: KeyboardAnimation?
private var didShowDeadline: Int64 = 0
private var shouldIgnoreKeyboardEvents = false

@objc public init(
handler: @escaping (NSString, NSNumber, NSNumber, NSNumber, NSNumber) -> Void,
Expand Down Expand Up @@ -95,6 +96,11 @@ public class KeyboardMovementObserver: NSObject {
name: UIResponder.keyboardDidHideNotification,
object: nil
)
NotificationCenter.default.addObserver(forName: .shouldIgnoreKeyboardEvents, object: nil, queue: .main) { notification in
if let userInfo = notification.userInfo, let value = userInfo["ignore"] as? Bool {
self.shouldIgnoreKeyboardEvents = value
}
}
}

private func setupKVObserver() {
Expand Down Expand Up @@ -129,9 +135,10 @@ public class KeyboardMovementObserver: NSObject {
if displayLink != nil {
return
}
print("\(keyboardView?.bounds.size.height) \(_keyboardHeight)")
// if keyboard height is not equal to its bounds - we can ignore
// values, since they'll be invalid and will cause UI jumps
if keyboardView?.bounds.size.height != _keyboardHeight {
if (keyboardView?.bounds.size.height ?? 0) != _keyboardHeight {
return
}

Expand Down Expand Up @@ -177,6 +184,8 @@ public class KeyboardMovementObserver: NSObject {
}

@objc func keyboardWillAppear(_ notification: Notification) {
guard !shouldIgnoreKeyboardEvents else { return }
print("keyboardWillAppear \(Date.currentTimeStamp)")
let (duration, frame) = notification.keyboardMetaData()
if let keyboardFrame = frame {
tag = UIResponder.current.reactViewTag
Expand All @@ -195,6 +204,8 @@ public class KeyboardMovementObserver: NSObject {
}

@objc func keyboardWillDisappear(_ notification: Notification) {
guard !shouldIgnoreKeyboardEvents else { return }
print("keyboardWillDisappear \(Date.currentTimeStamp)")
let (duration, _) = notification.keyboardMetaData()
tag = UIResponder.current.reactViewTag
self.duration = duration
Expand All @@ -209,16 +220,25 @@ public class KeyboardMovementObserver: NSObject {
}

@objc func keyboardDidAppear(_ notification: Notification) {
print("keyboardDidAppear \(Date.currentTimeStamp)")
let timestamp = Date.currentTimeStamp
let (duration, frame) = notification.keyboardMetaData()
if let keyboardFrame = frame {
let (position, _) = keyboardView.frameTransitionInWindow
let keyboardHeight = keyboardFrame.cgRectValue.size.height
tag = UIResponder.current.reactViewTag
self.keyboardHeight = keyboardHeight

guard !shouldIgnoreKeyboardEvents else {
shouldIgnoreKeyboardEvents = false
return
}

// if the event is caught in between it's highly likely that it could be a "resize" event
// so we just read actual keyboard frame value in this case
let height = timestamp >= didShowDeadline ? self.keyboardHeight : position - KeyboardAreaExtender.shared.offset
let height = timestamp >= didShowDeadline ? self.keyboardHeight : position
print("Using \(timestamp >= didShowDeadline ? "self.keyboardHeight" : "position")")
print("\(timestamp) vs \(didShowDeadline)")
// always limit progress to the maximum possible value
let progress = min(height / self.keyboardHeight, 1.0)

Expand All @@ -233,6 +253,8 @@ public class KeyboardMovementObserver: NSObject {
}

@objc func keyboardDidDisappear(_ notification: Notification) {
guard !shouldIgnoreKeyboardEvents else { return }
print("keyboardDidDisappear \(Date.currentTimeStamp)")
let (duration, _) = notification.keyboardMetaData()
tag = UIResponder.current.reactViewTag

Expand Down

0 comments on commit dd20a0c

Please sign in to comment.