@@ -899,6 +899,114 @@ void main() {
899
899
expect (X_SCROLL * 2 , scrollPosX);
900
900
expect (Y_SCROLL * 2 , scrollPosY);
901
901
});
902
+
903
+ testWidgets ('inputs are scrolled into view when focused' ,
904
+ (WidgetTester tester) async {
905
+ final String scrollTestPage = '''
906
+ <!DOCTYPE html>
907
+ <html>
908
+ <head>
909
+ <style>
910
+ input {
911
+ margin: 10000px 0;
912
+ }
913
+ #viewport {
914
+ position: fixed;
915
+ top:0;
916
+ bottom:0;
917
+ left:0;
918
+ right:0;
919
+ }
920
+ </style>
921
+ </head>
922
+ <body>
923
+ <div id="viewport"></div>
924
+ <input type="text" id="inputEl">
925
+ </body>
926
+ </html>
927
+ ''' ;
928
+
929
+ final String scrollTestPageBase64 =
930
+ base64Encode (const Utf8Encoder ().convert (scrollTestPage));
931
+
932
+ final Completer <void > pageLoaded = Completer <void >();
933
+ final Completer <WebViewController > controllerCompleter =
934
+ Completer <WebViewController >();
935
+
936
+ await tester.runAsync (() async {
937
+ await tester.pumpWidget (
938
+ Directionality (
939
+ textDirection: TextDirection .ltr,
940
+ child: SizedBox (
941
+ width: 200 ,
942
+ height: 200 ,
943
+ child: WebView (
944
+ initialUrl:
945
+ 'data:text/html;charset=utf-8;base64,$scrollTestPageBase64 ' ,
946
+ onWebViewCreated: (WebViewController controller) {
947
+ controllerCompleter.complete (controller);
948
+ },
949
+ onPageFinished: (String url) {
950
+ pageLoaded.complete (null );
951
+ },
952
+ javascriptMode: JavascriptMode .unrestricted,
953
+ ),
954
+ ),
955
+ ),
956
+ );
957
+ await Future .delayed (Duration (milliseconds: 20 ));
958
+ await tester.pump ();
959
+ });
960
+
961
+ final WebViewController controller = await controllerCompleter.future;
962
+ await pageLoaded.future;
963
+
964
+ final String viewportRectJSON = await controller.evaluateJavascript (
965
+ 'JSON.stringify(viewport.getBoundingClientRect())' );
966
+ final Map <String , dynamic > viewportRectRelativeToViewport =
967
+ jsonDecode (jsonDecode (viewportRectJSON));
968
+
969
+ // Check that the input is originally outside of the viewport.
970
+ {
971
+ final String inputClientRectJSON = await controller.evaluateJavascript (
972
+ 'JSON.stringify(inputEl.getBoundingClientRect())' );
973
+ final Map <String , dynamic > inputClientRectRelativeToViewport =
974
+ jsonDecode (jsonDecode (inputClientRectJSON));
975
+
976
+ expect (
977
+ inputClientRectRelativeToViewport['bottom' ] <=
978
+ viewportRectRelativeToViewport['bottom' ],
979
+ isFalse);
980
+ }
981
+
982
+ await controller.evaluateJavascript ('inputEl.focus()' );
983
+
984
+ // Check that focusing the input brought it into view.
985
+ {
986
+ final String inputClientRectJSON = await controller.evaluateJavascript (
987
+ 'JSON.stringify(inputEl.getBoundingClientRect())' );
988
+ final Map <String , dynamic > inputClientRectRelativeToViewport =
989
+ jsonDecode (jsonDecode (inputClientRectJSON));
990
+
991
+ expect (
992
+ inputClientRectRelativeToViewport['top' ] >=
993
+ viewportRectRelativeToViewport['top' ],
994
+ isTrue);
995
+ expect (
996
+ inputClientRectRelativeToViewport['bottom' ] <=
997
+ viewportRectRelativeToViewport['bottom' ],
998
+ isTrue);
999
+
1000
+ expect (
1001
+ inputClientRectRelativeToViewport['left' ] >=
1002
+ viewportRectRelativeToViewport['left' ],
1003
+ isTrue);
1004
+ expect (
1005
+ inputClientRectRelativeToViewport['right' ] <=
1006
+ viewportRectRelativeToViewport['right' ],
1007
+ isTrue);
1008
+ }
1009
+ });
902
1010
}, skip: ! Platform .isAndroid);
903
1011
904
1012
group ('NavigationDelegate' , () {
0 commit comments