Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
f8520927
Unverified
Commit
f8520927
authored
May 24, 2022
by
hellohuanlin
Committed by
GitHub
May 24, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add Focus support for iOS platform view (#103019)
parent
5c135cc5
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
95 additions
and
7 deletions
+95
-7
platform_views.dart
packages/flutter/lib/src/services/platform_views.dart
+6
-0
platform_view.dart
packages/flutter/lib/src/widgets/platform_view.dart
+20
-5
fake_platform_views.dart
packages/flutter/test/services/fake_platform_views.dart
+7
-0
platform_view_test.dart
packages/flutter/test/widgets/platform_view_test.dart
+62
-2
No files found.
packages/flutter/lib/src/services/platform_views.dart
View file @
f8520927
...
...
@@ -199,6 +199,8 @@ class PlatformViewsService {
/// factory for this view type must have been registered on the platform side.
/// Platform view factories are typically registered by plugin code.
///
/// `onFocus` is a callback that will be invoked when the UIKit view asks to
/// get the input focus.
/// The `id, `viewType, and `layoutDirection` parameters must not be null.
/// If `creationParams` is non null then `creationParamsCodec` must not be null.
static
Future
<
UiKitViewController
>
initUiKitView
({
...
...
@@ -207,6 +209,7 @@ class PlatformViewsService {
required
TextDirection
layoutDirection
,
dynamic
creationParams
,
MessageCodec
<
dynamic
>?
creationParamsCodec
,
VoidCallback
?
onFocus
,
})
async
{
assert
(
id
!=
null
);
assert
(
viewType
!=
null
);
...
...
@@ -227,6 +230,9 @@ class PlatformViewsService {
);
}
await
SystemChannels
.
platform_views
.
invokeMethod
<
void
>(
'create'
,
args
);
if
(
onFocus
!=
null
)
{
_instance
.
_focusCallbacks
[
id
]
=
onFocus
;
}
return
UiKitViewController
.
_
(
id
,
layoutDirection
);
}
}
...
...
packages/flutter/lib/src/widgets/platform_view.dart
View file @
f8520927
...
...
@@ -562,6 +562,7 @@ class _UiKitViewState extends State<UiKitView> {
UiKitViewController
?
_controller
;
TextDirection
?
_layoutDirection
;
bool
_initialized
=
false
;
late
FocusNode
_focusNode
;
static
final
Set
<
Factory
<
OneSequenceGestureRecognizer
>>
_emptyRecognizersSet
=
<
Factory
<
OneSequenceGestureRecognizer
>>{};
...
...
@@ -571,10 +572,14 @@ class _UiKitViewState extends State<UiKitView> {
if
(
_controller
==
null
)
{
return
const
SizedBox
.
expand
();
}
return
_UiKitPlatformView
(
controller:
_controller
!,
hitTestBehavior:
widget
.
hitTestBehavior
,
gestureRecognizers:
widget
.
gestureRecognizers
??
_emptyRecognizersSet
,
return
Focus
(
focusNode:
_focusNode
,
onFocusChange:
_onFocusChange
,
child:
_UiKitPlatformView
(
controller:
_controller
!,
hitTestBehavior:
widget
.
hitTestBehavior
,
gestureRecognizers:
widget
.
gestureRecognizers
??
_emptyRecognizersSet
,
),
);
}
...
...
@@ -639,13 +644,23 @@ class _UiKitViewState extends State<UiKitView> {
layoutDirection:
_layoutDirection
!,
creationParams:
widget
.
creationParams
,
creationParamsCodec:
widget
.
creationParamsCodec
,
onFocus:
()
{
_focusNode
.
requestFocus
();
}
);
if
(!
mounted
)
{
controller
.
dispose
();
return
;
}
widget
.
onPlatformViewCreated
?.
call
(
id
);
setState
(()
{
_controller
=
controller
;
});
setState
(()
{
_controller
=
controller
;
_focusNode
=
FocusNode
(
debugLabel:
'UiKitView(id:
$id
)'
);
});
}
void
_onFocusChange
(
bool
isFocused
)
{
// TODO(hellohuanlin): send 'TextInput.setPlatformViewClient' channel message to engine after the engine is updated to handle this message.
}
}
...
...
packages/flutter/test/services/fake_platform_views.dart
View file @
f8520927
...
...
@@ -340,6 +340,13 @@ class FakeIosPlatformViewsController {
_registeredViewTypes
.
add
(
viewType
);
}
void
invokeViewFocused
(
int
viewId
)
{
final
MethodCodec
codec
=
SystemChannels
.
platform_views
.
codec
;
final
ByteData
data
=
codec
.
encodeMethodCall
(
MethodCall
(
'viewFocused'
,
viewId
));
ServicesBinding
.
instance
.
defaultBinaryMessenger
.
handlePlatformMessage
(
SystemChannels
.
platform_views
.
name
,
data
,
(
ByteData
?
data
)
{});
}
Future
<
dynamic
>
_onMethodCall
(
MethodCall
call
)
{
switch
(
call
.
method
)
{
case
'create'
:
...
...
packages/flutter/test/widgets/platform_view_test.dart
View file @
f8520927
...
...
@@ -1978,7 +1978,7 @@ void main() {
},
);
testWidgets
(
'
Android
View rebuilt with same gestureRecognizers'
,
(
WidgetTester
tester
)
async
{
testWidgets
(
'
UiKit
View rebuilt with same gestureRecognizers'
,
(
WidgetTester
tester
)
async
{
final
FakeIosPlatformViewsController
viewsController
=
FakeIosPlatformViewsController
();
viewsController
.
registerViewType
(
'webview'
);
...
...
@@ -2012,6 +2012,59 @@ void main() {
expect
(
factoryInvocationCount
,
1
);
});
testWidgets
(
'UiKitView can take input focus'
,
(
WidgetTester
tester
)
async
{
final
int
currentViewId
=
platformViewsRegistry
.
getNextPlatformViewId
();
final
FakeIosPlatformViewsController
viewsController
=
FakeIosPlatformViewsController
();
viewsController
.
registerViewType
(
'webview'
);
final
GlobalKey
containerKey
=
GlobalKey
();
await
tester
.
pumpWidget
(
Center
(
child:
Column
(
children:
<
Widget
>[
const
SizedBox
(
width:
200.0
,
height:
100.0
,
child:
UiKitView
(
viewType:
'webview'
,
layoutDirection:
TextDirection
.
ltr
),
),
Focus
(
debugLabel:
'container'
,
child:
Container
(
key:
containerKey
),
),
],
),
),
);
// First frame is before the platform view was created so the render object
// is not yet in the tree.
await
tester
.
pump
();
final
Focus
uiKitViewFocusWidget
=
tester
.
widget
(
find
.
descendant
(
of:
find
.
byType
(
UiKitView
),
matching:
find
.
byType
(
Focus
),
),
);
final
FocusNode
uiKitViewFocusNode
=
uiKitViewFocusWidget
.
focusNode
!;
final
Element
containerElement
=
tester
.
element
(
find
.
byKey
(
containerKey
));
final
FocusNode
containerFocusNode
=
Focus
.
of
(
containerElement
);
containerFocusNode
.
requestFocus
();
await
tester
.
pump
();
expect
(
containerFocusNode
.
hasFocus
,
isTrue
);
expect
(
uiKitViewFocusNode
.
hasFocus
,
isFalse
);
viewsController
.
invokeViewFocused
(
currentViewId
+
1
);
await
tester
.
pump
();
expect
(
containerFocusNode
.
hasFocus
,
isFalse
);
expect
(
uiKitViewFocusNode
.
hasFocus
,
isTrue
);
});
testWidgets
(
'UiKitView has correct semantics'
,
(
WidgetTester
tester
)
async
{
final
SemanticsHandle
handle
=
tester
.
ensureSemantics
();
final
int
currentViewId
=
platformViewsRegistry
.
getNextPlatformViewId
();
...
...
@@ -2039,7 +2092,14 @@ void main() {
// is not yet in the tree.
await
tester
.
pump
();
final
SemanticsNode
semantics
=
tester
.
getSemantics
(
find
.
byType
(
UiKitView
));
final
SemanticsNode
semantics
=
tester
.
getSemantics
(
find
.
descendant
(
of:
find
.
byType
(
UiKitView
),
matching:
find
.
byWidgetPredicate
(
(
Widget
widget
)
=>
widget
.
runtimeType
.
toString
()
==
'_UiKitPlatformView'
,
),
),
);
expect
(
semantics
.
platformViewId
,
currentViewId
+
1
);
expect
(
semantics
.
rect
,
const
Rect
.
fromLTWH
(
0
,
0
,
200
,
100
));
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment