diff --git a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md index 4b90957df14..44577673b43 100644 --- a/packages/webview_flutter/webview_flutter_android/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_android/CHANGELOG.md @@ -1,3 +1,7 @@ +## 4.4.0 + +* Adds support to set the over-scroll mode for the WebView. See `AndroidWebViewController.setOverScrollMode`. + ## 4.3.5 * Adds internal wrapper methods for native `WebViewClient`. diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/AndroidWebkitLibrary.g.kt b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/AndroidWebkitLibrary.g.kt index a347b77fa97..fdbbd259af3 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/AndroidWebkitLibrary.g.kt +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/AndroidWebkitLibrary.g.kt @@ -642,6 +642,7 @@ private class AndroidWebkitLibraryPigeonProxyApiBaseCodec( value is String || value is FileChooserMode || value is ConsoleMessageLevel || + value is OverScrollMode || value is SslErrorType || value == null) { super.writeValue(stream, value) @@ -814,6 +815,31 @@ enum class ConsoleMessageLevel(val raw: Int) { } } +/** + * The over-scroll mode for a view. + * + * See https://developer.android.com/reference/android/view/View#OVER_SCROLL_ALWAYS. + */ +enum class OverScrollMode(val raw: Int) { + /** Always allow a user to over-scroll this view, provided it is a view that can scroll. */ + ALWAYS(0), + /** + * Allow a user to over-scroll this view only if the content is large enough to meaningfully + * scroll, provided it is a view that can scroll. + */ + IF_CONTENT_SCROLLS(1), + /** Never allow a user to over-scroll this view. */ + NEVER(2), + /** The type is not recognized by this wrapper. */ + UNKNOWN(3); + + companion object { + fun ofRaw(raw: Int): OverScrollMode? { + return values().firstOrNull { it.raw == raw } + } + } +} + /** * Type of error for a SslCertificate. * @@ -852,6 +878,9 @@ private open class AndroidWebkitLibraryPigeonCodec : StandardMessageCodec() { return (readValue(buffer) as Long?)?.let { ConsoleMessageLevel.ofRaw(it.toInt()) } } 131.toByte() -> { + return (readValue(buffer) as Long?)?.let { OverScrollMode.ofRaw(it.toInt()) } + } + 132.toByte() -> { return (readValue(buffer) as Long?)?.let { SslErrorType.ofRaw(it.toInt()) } } else -> super.readValueOfType(type, buffer) @@ -868,10 +897,14 @@ private open class AndroidWebkitLibraryPigeonCodec : StandardMessageCodec() { stream.write(130) writeValue(stream, value.raw) } - is SslErrorType -> { + is OverScrollMode -> { stream.write(131) writeValue(stream, value.raw) } + is SslErrorType -> { + stream.write(132) + writeValue(stream, value.raw) + } else -> super.writeValue(stream, value) } } @@ -4780,6 +4813,9 @@ abstract class PigeonApiView( /** Return the scrolled position of this view. */ abstract fun getScrollPosition(pigeon_instance: android.view.View): WebViewPoint + /** Set the over-scroll mode for this view. */ + abstract fun setOverScrollMode(pigeon_instance: android.view.View, mode: OverScrollMode) + companion object { @Suppress("LocalVariableName") fun setUpMessageHandlers(binaryMessenger: BinaryMessenger, api: PigeonApiView?) { @@ -4852,6 +4888,30 @@ abstract class PigeonApiView( channel.setMessageHandler(null) } } + run { + val channel = + BasicMessageChannel( + binaryMessenger, + "dev.flutter.pigeon.webview_flutter_android.View.setOverScrollMode", + codec) + if (api != null) { + channel.setMessageHandler { message, reply -> + val args = message as List + val pigeon_instanceArg = args[0] as android.view.View + val modeArg = args[1] as OverScrollMode + val wrapped: List = + try { + api.setOverScrollMode(pigeon_instanceArg, modeArg) + listOf(null) + } catch (exception: Throwable) { + wrapError(exception) + } + reply.reply(wrapped) + } + } else { + channel.setMessageHandler(null) + } + } } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/ViewProxyApi.java b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/ViewProxyApi.java index e5efbd15f81..e4925f9912d 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/ViewProxyApi.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/main/java/io/flutter/plugins/webviewflutter/ViewProxyApi.java @@ -19,6 +19,12 @@ public ViewProxyApi(@NonNull ProxyApiRegistrar pigeonRegistrar) { super(pigeonRegistrar); } + @NonNull + @Override + public ProxyApiRegistrar getPigeonRegistrar() { + return (ProxyApiRegistrar) super.getPigeonRegistrar(); + } + @Override public void scrollTo(@NonNull View pigeon_instance, long x, long y) { pigeon_instance.scrollTo((int) x, (int) y); @@ -34,4 +40,21 @@ public void scrollBy(@NonNull View pigeon_instance, long x, long y) { public WebViewPoint getScrollPosition(@NonNull View pigeon_instance) { return new WebViewPoint(pigeon_instance.getScrollX(), pigeon_instance.getScrollY()); } + + @Override + public void setOverScrollMode(@NonNull View pigeon_instance, @NonNull OverScrollMode mode) { + switch (mode) { + case ALWAYS: + pigeon_instance.setOverScrollMode(View.OVER_SCROLL_ALWAYS); + break; + case IF_CONTENT_SCROLLS: + pigeon_instance.setOverScrollMode(View.OVER_SCROLL_IF_CONTENT_SCROLLS); + break; + case NEVER: + pigeon_instance.setOverScrollMode(View.OVER_SCROLL_NEVER); + break; + case UNKNOWN: + throw getPigeonRegistrar().createUnknownEnumException(OverScrollMode.UNKNOWN); + } + } } diff --git a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/ViewTest.java b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/ViewTest.java index 2ae41983d44..4f806e5812d 100644 --- a/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/ViewTest.java +++ b/packages/webview_flutter/webview_flutter_android/android/src/test/java/io/flutter/plugins/webviewflutter/ViewTest.java @@ -49,4 +49,15 @@ public void getScrollPosition() { assertEquals(value.getX(), api.getScrollPosition(instance).getX()); assertEquals(value.getY(), api.getScrollPosition(instance).getY()); } + + @Test + public void setOverScrollMode() { + final PigeonApiView api = new TestProxyApiRegistrar().getPigeonApiView(); + + final View instance = mock(View.class); + final OverScrollMode mode = io.flutter.plugins.webviewflutter.OverScrollMode.ALWAYS; + api.setOverScrollMode(instance, mode); + + verify(instance).setOverScrollMode(View.OVER_SCROLL_ALWAYS); + } } diff --git a/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml index c22d7dc7022..de6c69e7806 100644 --- a/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/example/pubspec.yaml @@ -17,7 +17,7 @@ dependencies: # The example app is bundled with the plugin so we use a path dependency on # the parent directory to use the current plugin's version. path: ../ - webview_flutter_platform_interface: ^2.10.0 + webview_flutter_platform_interface: ^2.11.0 dev_dependencies: espresso: ^0.4.0 diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webkit.g.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webkit.g.dart index f67bae562ad..fe377e68926 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webkit.g.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webkit.g.dart @@ -521,6 +521,25 @@ enum ConsoleMessageLevel { unknown, } +/// The over-scroll mode for a view. +/// +/// See https://developer.android.com/reference/android/view/View#OVER_SCROLL_ALWAYS. +enum OverScrollMode { + /// Always allow a user to over-scroll this view, provided it is a view that + /// can scroll. + always, + + /// Allow a user to over-scroll this view only if the content is large enough + /// to meaningfully scroll, provided it is a view that can scroll. + ifContentScrolls, + + /// Never allow a user to over-scroll this view. + never, + + /// The type is not recognized by this wrapper. + unknown, +} + /// Type of error for a SslCertificate. /// /// See https://developer.android.com/reference/android/net/http/SslError#SSL_DATE_INVALID. @@ -560,9 +579,12 @@ class _PigeonCodec extends StandardMessageCodec { } else if (value is ConsoleMessageLevel) { buffer.putUint8(130); writeValue(buffer, value.index); - } else if (value is SslErrorType) { + } else if (value is OverScrollMode) { buffer.putUint8(131); writeValue(buffer, value.index); + } else if (value is SslErrorType) { + buffer.putUint8(132); + writeValue(buffer, value.index); } else { super.writeValue(buffer, value); } @@ -578,6 +600,9 @@ class _PigeonCodec extends StandardMessageCodec { final int? value = readValue(buffer) as int?; return value == null ? null : ConsoleMessageLevel.values[value]; case 131: + final int? value = readValue(buffer) as int?; + return value == null ? null : OverScrollMode.values[value]; + case 132: final int? value = readValue(buffer) as int?; return value == null ? null : SslErrorType.values[value]; default: @@ -6586,6 +6611,36 @@ class View extends PigeonInternalProxyApiBaseClass { } } + /// Set the over-scroll mode for this view. + Future setOverScrollMode(OverScrollMode mode) async { + final _PigeonInternalProxyApiBaseCodec pigeonChannelCodec = + _pigeonVar_codecView; + final BinaryMessenger? pigeonVar_binaryMessenger = pigeon_binaryMessenger; + const String pigeonVar_channelName = + 'dev.flutter.pigeon.webview_flutter_android.View.setOverScrollMode'; + final BasicMessageChannel pigeonVar_channel = + BasicMessageChannel( + pigeonVar_channelName, + pigeonChannelCodec, + binaryMessenger: pigeonVar_binaryMessenger, + ); + final Future pigeonVar_sendFuture = + pigeonVar_channel.send([this, mode]); + final List? pigeonVar_replyList = + await pigeonVar_sendFuture as List?; + if (pigeonVar_replyList == null) { + throw _createConnectionError(pigeonVar_channelName); + } else if (pigeonVar_replyList.length > 1) { + throw PlatformException( + code: pigeonVar_replyList[0]! as String, + message: pigeonVar_replyList[1] as String?, + details: pigeonVar_replyList[2], + ); + } else { + return; + } + } + @override View pigeon_copy() { return View.pigeon_detached( diff --git a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart index 7317affbd85..c8326529e59 100644 --- a/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_android/lib/src/android_webview_controller.dart @@ -731,6 +731,24 @@ class AndroidWebViewController extends PlatformWebViewController { _onJavaScriptPrompt = onJavaScriptTextInputDialog; return _webChromeClient.setSynchronousReturnValueForOnJsPrompt(true); } + + @override + Future setOverScrollMode(WebViewOverScrollMode mode) { + return switch (mode) { + WebViewOverScrollMode.always => _webView.setOverScrollMode( + android_webview.OverScrollMode.always, + ), + WebViewOverScrollMode.ifContentScrolls => _webView.setOverScrollMode( + android_webview.OverScrollMode.ifContentScrolls, + ), + WebViewOverScrollMode.never => _webView.setOverScrollMode( + android_webview.OverScrollMode.never, + ), + // This prevents future additions from causing a breaking change. + // ignore: unreachable_switch_case + _ => throw UnsupportedError('Android does not support $mode.'), + }; + } } /// Android implementation of [PlatformWebViewPermissionRequest]. diff --git a/packages/webview_flutter/webview_flutter_android/pigeons/android_webkit.dart b/packages/webview_flutter/webview_flutter_android/pigeons/android_webkit.dart index cc173f8f875..42a15fc68bd 100644 --- a/packages/webview_flutter/webview_flutter_android/pigeons/android_webkit.dart +++ b/packages/webview_flutter/webview_flutter_android/pigeons/android_webkit.dart @@ -80,6 +80,25 @@ enum ConsoleMessageLevel { unknown, } +/// The over-scroll mode for a view. +/// +/// See https://developer.android.com/reference/android/view/View#OVER_SCROLL_ALWAYS. +enum OverScrollMode { + /// Always allow a user to over-scroll this view, provided it is a view that + /// can scroll. + always, + + /// Allow a user to over-scroll this view only if the content is large enough + /// to meaningfully scroll, provided it is a view that can scroll. + ifContentScrolls, + + /// Never allow a user to over-scroll this view. + never, + + /// The type is not recognized by this wrapper. + unknown, +} + /// Type of error for a SslCertificate. /// /// See https://developer.android.com/reference/android/net/http/SslError#SSL_DATE_INVALID. @@ -832,6 +851,9 @@ abstract class View { /// Return the scrolled position of this view. WebViewPoint getScrollPosition(); + + /// Set the over-scroll mode for this view. + void setOverScrollMode(OverScrollMode mode); } /// A callback interface used by the host application to set the Geolocation diff --git a/packages/webview_flutter/webview_flutter_android/pubspec.yaml b/packages/webview_flutter/webview_flutter_android/pubspec.yaml index 915ac70f768..d58ee58848a 100644 --- a/packages/webview_flutter/webview_flutter_android/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_android/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_android description: A Flutter plugin that provides a WebView widget on Android. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_android issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 4.3.5 +version: 4.4.0 environment: sdk: ^3.6.0 @@ -20,14 +20,14 @@ flutter: dependencies: flutter: sdk: flutter - webview_flutter_platform_interface: ^2.10.0 + webview_flutter_platform_interface: ^2.11.0 dev_dependencies: build_runner: ^2.1.4 flutter_test: sdk: flutter mockito: ^5.4.4 - pigeon: ^25.2.0 + pigeon: ^25.3.0 topics: - html diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart index 4fd19cf68a8..87bab7f8f5d 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.dart @@ -1624,6 +1624,21 @@ void main() { verify(mockSettings.setTextZoom(100)).called(1); }); + test('setOverScrollMode', () async { + final MockWebView mockWebView = MockWebView(); + final AndroidWebViewController controller = createControllerWithMocks( + mockWebView: mockWebView, + ); + + await controller.setOverScrollMode(WebViewOverScrollMode.always); + + verify( + mockWebView.setOverScrollMode( + android_webview.OverScrollMode.always, + ), + ).called(1); + }); + test('webViewIdentifier', () { final MockWebView mockWebView = MockWebView(); diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart index 02bcae66842..10247006657 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_controller_test.mocks.dart @@ -688,6 +688,14 @@ class MockAndroidWebViewController extends _i1.Mock returnValue: _i8.Future.value(), returnValueForMissingStub: _i8.Future.value(), ) as _i8.Future); + + @override + _i8.Future setOverScrollMode(_i3.WebViewOverScrollMode? mode) => + (super.noSuchMethod( + Invocation.method(#setOverScrollMode, [mode]), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); } /// A class which mocks [AndroidWebViewProxy]. @@ -2476,6 +2484,14 @@ class MockWebView extends _i1.Mock implements _i2.WebView { ), ), ) as _i8.Future<_i2.WebViewPoint>); + + @override + _i8.Future setOverScrollMode(_i2.OverScrollMode? mode) => + (super.noSuchMethod( + Invocation.method(#setOverScrollMode, [mode]), + returnValue: _i8.Future.value(), + returnValueForMissingStub: _i8.Future.value(), + ) as _i8.Future); } /// A class which mocks [WebViewClient]. diff --git a/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.mocks.dart b/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.mocks.dart index 8d6b892fcfc..b44e59a8c08 100644 --- a/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_android/test/android_webview_cookie_manager_test.mocks.dart @@ -472,4 +472,12 @@ class MockAndroidWebViewController extends _i1.Mock returnValue: _i5.Future.value(), returnValueForMissingStub: _i5.Future.value(), ) as _i5.Future); + + @override + _i5.Future setOverScrollMode(_i3.WebViewOverScrollMode? mode) => + (super.noSuchMethod( + Invocation.method(#setOverScrollMode, [mode]), + returnValue: _i5.Future.value(), + returnValueForMissingStub: _i5.Future.value(), + ) as _i5.Future); } diff --git a/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_widget_test.mocks.dart b/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_widget_test.mocks.dart index b7d9898b9c0..6eebf3a56d8 100644 --- a/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_widget_test.mocks.dart +++ b/packages/webview_flutter/webview_flutter_android/test/legacy/webview_android_widget_test.mocks.dart @@ -546,6 +546,14 @@ class MockWebView extends _i1.Mock implements _i2.WebView { ), ), ) as _i4.Future<_i2.WebViewPoint>); + + @override + _i4.Future setOverScrollMode(_i2.OverScrollMode? mode) => + (super.noSuchMethod( + Invocation.method(#setOverScrollMode, [mode]), + returnValue: _i4.Future.value(), + returnValueForMissingStub: _i4.Future.value(), + ) as _i4.Future); } /// A class which mocks [WebResourceRequest]. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md index 11dbc2c5a86..be8a5296610 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md +++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md @@ -1,3 +1,7 @@ +## 3.19.0 + +* Adds support to set the over-scroll mode for the WebView. See `WebKitWebViewController.setOverScrollMode`. + ## 3.18.6 * Fixes `PlatformException` when calling `loadFlutterAsset` on macOS. diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml index f8ed12551d5..fa7f2114200 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml @@ -10,7 +10,7 @@ dependencies: flutter: sdk: flutter path_provider: ^2.0.6 - webview_flutter_platform_interface: ^2.10.0 + webview_flutter_platform_interface: ^2.11.0 webview_flutter_wkwebview: # When depending on this package from a real application you should use: # webview_flutter: ^x.y.z diff --git a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart index 843c73f3de3..2a329541cd5 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/lib/src/webkit_webview_controller.dart @@ -768,6 +768,30 @@ window.addEventListener("error", function(e) { await controller.addUserScript(overrideScript); } + @override + Future setOverScrollMode(WebViewOverScrollMode mode) { + return switch (mode) { + WebViewOverScrollMode.always => Future.wait( + >[ + _webView.scrollView.setBounces(true), + _webView.scrollView.setAlwaysBounceHorizontal(true), + _webView.scrollView.setAlwaysBounceVertical(true), + ], + ), + WebViewOverScrollMode.ifContentScrolls => Future.wait( + >[ + _webView.scrollView.setBounces(true), + _webView.scrollView.setAlwaysBounceHorizontal(false), + _webView.scrollView.setAlwaysBounceVertical(false), + ], + ), + WebViewOverScrollMode.never => _webView.scrollView.setBounces(false), + // This prevents future additions from causing a breaking change. + // ignore: unreachable_switch_case + _ => throw UnsupportedError('This platform does not support $mode.'), + }; + } + // WKWebView does not support removing a single user script, so all user // scripts and all message handlers are removed instead. And the JavaScript // channels that shouldn't be removed are re-registered. Note that this diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml index 73efba1dc8b..535e997a026 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml +++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml @@ -2,7 +2,7 @@ name: webview_flutter_wkwebview description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control. repository: https://github.com/flutter/packages/tree/main/packages/webview_flutter/webview_flutter_wkwebview issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+webview%22 -version: 3.18.6 +version: 3.19.0 environment: sdk: ^3.5.0 @@ -25,7 +25,7 @@ dependencies: flutter: sdk: flutter path: ^1.8.0 - webview_flutter_platform_interface: ^2.10.0 + webview_flutter_platform_interface: ^2.11.0 dev_dependencies: build_runner: ^2.1.5 diff --git a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart index e6a350de4e6..bc2c612d2a7 100644 --- a/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart +++ b/packages/webview_flutter/webview_flutter_wkwebview/test/webkit_webview_controller_test.dart @@ -1383,6 +1383,30 @@ void main() { expect(urlChange.url, null); }); + test('setOverScrollMode', () async { + final MockUIScrollView mockScrollView = MockUIScrollView(); + + final WebKitWebViewController controller = createControllerWithMocks( + mockScrollView: mockScrollView, + ); + + await controller.setOverScrollMode(WebViewOverScrollMode.always); + verify(mockScrollView.setBounces(true)); + verify(mockScrollView.setAlwaysBounceVertical(true)); + verify(mockScrollView.setAlwaysBounceHorizontal(true)); + + clearInteractions(mockScrollView); + await controller + .setOverScrollMode(WebViewOverScrollMode.ifContentScrolls); + verify(mockScrollView.setBounces(true)); + verify(mockScrollView.setAlwaysBounceVertical(false)); + verify(mockScrollView.setAlwaysBounceHorizontal(false)); + + clearInteractions(mockScrollView); + await controller.setOverScrollMode(WebViewOverScrollMode.never); + verify(mockScrollView.setBounces(false)); + }); + test('webViewIdentifier', () { final PigeonInstanceManager instanceManager = TestInstanceManager();