fix: predictive back gesture handler (correct end event) #814
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
📜 Description
Fixed incorrect
end
event after cancelling predictive back gesture.💡 Motivation and Context
The problem was in fact that when keyboard gets shown in
onEnd
callback we get keyboard height as0
, because insets were not applied yet.I had this problem two years ago (when I implemented interactive keyboard dismissal), but back to the times I solved it via adding
InteractiveProvider.isShown
and it was working well, because the only one class could control keyboard position and it was my class. However starting from Android 15 keyboard position can be controlled by OS itself, so the trick withInteractiveProvider.isShown
is not working anymore.After discovering various approaches how to handle it I found only two ways:
1️⃣ Pre-save insets in
onApplyWindowInsets
While it seems preferable option, I still don't understand how it can be utilized in that fix, because
onApplyWindowInsets
will be dispatched in the beginning of the animation and inonEnd
we will not be able to determine whether keyboard has been actually closed or returned back.Warning
The approach with saving last keyboard height in
onProgress
handler and based on that dispatch an event inonEnd
may be not good, because keyboard animation can be interrupted and potentially it can cause more bugs, see #704 for more details2️⃣ Check insets after layout pass
This seems to be one and the most reliable solution (though it adds a delay to
onEnd
event, but in my understanding it's not very critical). With this approach we can be sure, that all new insets are applied and we can reak keyboard frame properly.Upcoming questions that popped up in my head:
InteractiveKeyboardProvider
completely/should we consider predictive back gesture dismissal as interactive keyboard dismissal - is a good question, but if we do this, we'll treat back predictive gesture as interactive keyboard dismissal (in fact it is interactive dismissal), and in this case we'll sendonInteractive
instead ofonMove
. It can be a breaking change and people (including me) may associateonInteractive
event only to be present withKeyboardGestureArea
, so for now let's keep it for a sake of backward compatibility.start
/onApplyInsets
and re-use it there? - at the moment I don't understand how memoization of insets inonApplyInsets
/onStart
can help us to detect final keyboard position inonEnd
. Maybe it's doable, but for now let's stick with async approach. If we discover a new way how to handle everything synchronously we always can re-work that piece of the code and improve it 😎Closes #810
📢 Changelog
Android
isKeyboardInteractive
getter;onEnd
body inRunnable
;isKeyboardInteractive
either executerunnable
immediately or after a layout pass;InteractiveProvider.isShown
;🤔 How Has This Been Tested?
Tested manually on Pixel 7 Pro (Android 15).
📸 Screenshots (if appropriate):
telegram-cloud-document-2-5312269435799625339.mp4
📝 Checklist