Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit 7bcf9f4

Browse files
authored
Flutter iOS Interactive Keyboard: Fixing Animation Issue (#44514)
This PR addresses an issue with the animation of the keyboard. In iOS 16.0 a delay was included in UIView becomeFirstResponder where the areAnimationsEnabled boolean is no longer immediately read. In response to this issue a delay is added that allows for the animation to be properly disabled. Design Document: https://docs.google.com/document/d/1-T7_0mSkXzPaWxveeypIzzzAdyo-EEuP5V84161foL4/edit?pli=1 Issues Address: flutter/flutter#57609 [C++, Objective-C, Java style guides]: https://github.com/flutter/engine/blob/main/CONTRIBUTING.md#style
1 parent 8f67d07 commit 7bcf9f4

File tree

2 files changed

+33
-2
lines changed

2 files changed

+33
-2
lines changed

shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.mm

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@
2121
// it is activated.
2222
static constexpr double kUITextInputAccessibilityEnablingDelaySeconds = 0.5;
2323

24+
// A delay before reenabling the UIView areAnimationsEnabled to YES
25+
// in order for becomeFirstResponder to receive the proper value
26+
static const NSTimeInterval kKeyboardAnimationDelaySeconds = 0.1;
27+
2428
// The "canonical" invalid CGRect, similar to CGRectNull, used to
2529
// indicate a CGRect involved in firstRectForRange calculation is
2630
// invalid. The specific value is chosen so that if firstRectForRange
@@ -2369,8 +2373,13 @@ - (void)dismissKeyboardScreenshot {
23692373
- (void)showKeyboardAndRemoveScreenshot {
23702374
[UIView setAnimationsEnabled:NO];
23712375
[_cachedFirstResponder becomeFirstResponder];
2372-
[UIView setAnimationsEnabled:YES];
2373-
[self dismissKeyboardScreenshot];
2376+
// UIKit does not immediately access the areAnimationsEnabled Boolean so a delay is needed before
2377+
// returned
2378+
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, kKeyboardAnimationDelaySeconds * NSEC_PER_SEC),
2379+
dispatch_get_main_queue(), ^{
2380+
[UIView setAnimationsEnabled:YES];
2381+
[self dismissKeyboardScreenshot];
2382+
});
23742383
}
23752384

23762385
- (void)handlePointerMove:(CGFloat)pointerY {

shell/platform/darwin/ios/framework/Source/FlutterTextInputPluginTest.mm

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ - (void)cleanUpViewHierarchy:(BOOL)includeActiveView
7575
- (UIView*)hostView;
7676
- (void)addToInputParentViewIfNeeded:(FlutterTextInputView*)inputView;
7777
- (void)startLiveTextInput;
78+
- (void)showKeyboardAndRemoveScreenshot;
79+
7880
@end
7981

8082
@interface FlutterTextInputPluginTest : XCTestCase
@@ -2890,5 +2892,25 @@ - (void)testInteractiveKeyboardKeyboardAnimatesToDismissalPositionalOnPointerUp
28902892
}];
28912893
textInputPlugin.cachedFirstResponder = nil;
28922894
}
2895+
- (void)testInteractiveKeyboardShowKeyboardAndRemoveScreenshotAnimationIsNotImmediatelyEnable {
2896+
[UIView setAnimationsEnabled:YES];
2897+
[textInputPlugin showKeyboardAndRemoveScreenshot];
2898+
XCTAssertFalse(
2899+
UIView.areAnimationsEnabled,
2900+
@"The animation should still be disabled following showKeyboardAndRemoveScreenshot");
2901+
}
2902+
2903+
- (void)testInteractiveKeyboardShowKeyboardAndRemoveScreenshotAnimationIsReenabledAfterDelay {
2904+
[UIView setAnimationsEnabled:YES];
2905+
[textInputPlugin showKeyboardAndRemoveScreenshot];
2906+
2907+
NSPredicate* predicate = [NSPredicate predicateWithBlock:^BOOL(id item, NSDictionary* bindings) {
2908+
// This will be enabled after a delay
2909+
return UIView.areAnimationsEnabled;
2910+
}];
2911+
XCTNSPredicateExpectation* expectation =
2912+
[[XCTNSPredicateExpectation alloc] initWithPredicate:predicate object:nil];
2913+
[self waitForExpectations:@[ expectation ] timeout:10.0];
2914+
}
28932915

28942916
@end

0 commit comments

Comments
 (0)