-
Notifications
You must be signed in to change notification settings - Fork 6k
Add focus support for platform view #33093
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
- Loading branch information
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -986,6 +986,37 @@ - (void)flutterTextInputView:(FlutterTextInputView*)textInputView | |
| arguments:@[ @(client) ]]; | ||
| } | ||
|
|
||
| - (void)flutterTextInputViewDidResignFirstResponder:(FlutterTextInputView*)textInputView { | ||
| // Platform view's first responder detection logic | ||
| // | ||
| // All text input widgets (e.g. EditableText) are backed by a dummy UITextInput view | ||
| // in the text input plugin. When this dummy UITextInput view resigns first responder, | ||
hellohuanlin marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // check if any platform view becomes first responder. If any platform view becomes | ||
| // first responder, send a "viewFocused" channel message to inform the framework to un-focus | ||
| // the previously focused text input. | ||
| // | ||
| // Caveat: | ||
| // 1. This detection logic does not cover the scenario when a platform view becomes | ||
| // first responder without any flutter text input resigning its first responder status | ||
| // (e.g. user tapping on platform view first). For now it works fine because there can only be | ||
|
||
| // one first responder in iOS, so we do not need to keep platform view's first responder status | ||
| // in the text input plugin (which is different from Android implementation). | ||
| // | ||
| // 2. This detection logic assumes that all text input widgets are backed by a dummy | ||
| // UITextInput view in the text input plugin, which may not hold true in the future. | ||
|
|
||
| // Have to check in the next run loop, because iOS requests the previous first responder to | ||
| // resign before requesting the next view to become first responder. | ||
| dispatch_async(dispatch_get_main_queue(), ^(void) { | ||
| long platform_view_id = self.platformViewsController->FindFirstResponderPlatformViewId(); | ||
| if (platform_view_id == -1) { | ||
| return; | ||
| } | ||
|
|
||
| [_platformViewsChannel.get() invokeMethod:@"viewFocused" arguments:@(platform_view_id)]; | ||
| }); | ||
| } | ||
|
|
||
| #pragma mark - Undo Manager Delegate | ||
|
|
||
| - (void)flutterUndoManagerPlugin:(FlutterUndoManagerPlugin*)undoManagerPlugin | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -39,6 +39,7 @@ | |
| static NSString* const kShowMethod = @"TextInput.show"; | ||
| static NSString* const kHideMethod = @"TextInput.hide"; | ||
| static NSString* const kSetClientMethod = @"TextInput.setClient"; | ||
| static NSString* const kSetPlatformViewClientMethod = @"TextInput.setPlatformViewClient"; | ||
| static NSString* const kSetEditingStateMethod = @"TextInput.setEditingState"; | ||
| static NSString* const kClearClientMethod = @"TextInput.clearClient"; | ||
| static NSString* const kSetEditableSizeAndTransformMethod = | ||
|
|
@@ -1075,6 +1076,14 @@ - (BOOL)canBecomeFirstResponder { | |
| return _textInputClient != 0; | ||
| } | ||
|
|
||
| - (BOOL)resignFirstResponder { | ||
| BOOL success = [super resignFirstResponder]; | ||
| if (success) { | ||
| [self.textInputDelegate flutterTextInputViewDidResignFirstResponder:self]; | ||
| } | ||
| return success; | ||
| } | ||
|
|
||
| - (BOOL)canPerformAction:(SEL)action withSender:(id)sender { | ||
| // When scribble is available, the FlutterTextInputView will display the native toolbar unless | ||
| // these text editing actions are disabled. | ||
|
|
@@ -2071,6 +2080,9 @@ - (void)handleMethodCall:(FlutterMethodCall*)call result:(FlutterResult)result { | |
| } else if ([method isEqualToString:kSetClientMethod]) { | ||
| [self setTextInputClient:[args[0] intValue] withConfiguration:args[1]]; | ||
| result(nil); | ||
| } else if ([method isEqualToString:kSetPlatformViewClientMethod]) { | ||
| [self setPlatformViewTextInputClient:[args[@"platformViewId"] longValue]]; | ||
| result(nil); | ||
| } else if ([method isEqualToString:kSetEditingStateMethod]) { | ||
| [self setTextInputEditingState:args]; | ||
| result(nil); | ||
|
|
@@ -2187,6 +2199,16 @@ - (void)triggerAutofillSave:(BOOL)saveEntries { | |
| [self addToInputParentViewIfNeeded:_activeView]; | ||
| } | ||
|
|
||
| - (void)setPlatformViewTextInputClient:(long)platformViewID { | ||
hellohuanlin marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| // No need to track the platformViewID for now (unlike in Android), because in iOS there can | ||
| // only be one single first responder. When a platform view becomes first responder, hide | ||
| // this dummy text input view (`_activeView`) for the previously focused widget. | ||
| [self removeEnableFlutterTextInputViewAccessibilityTimer]; | ||
| _activeView.accessibilityEnabled = NO; | ||
| [_activeView removeFromSuperview]; | ||
| [_inputHider removeFromSuperview]; | ||
| } | ||
|
|
||
|
||
| - (void)setTextInputClient:(int)client withConfiguration:(NSDictionary*)configuration { | ||
| [self resetAllClientIds]; | ||
| // Hide all input views from autofill, only make those in the new configuration visible | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.