Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
dd1196d
Recreating PR from flutter/plugins
TheVinhLuong Mar 11, 2023
d91b421
Merge branch 'master' into webview-scroll-listener
TheVinhLuong Mar 11, 2023
2a9b827
[webview_android] Remove enableContentOffsetChangedListener
TheVinhLuong Apr 1, 2023
07d30ef
Merge branch 'master' into webview-scroll-listener
TheVinhLuong Apr 1, 2023
5a80183
Fixup based on code review
TheVinhLuong Apr 14, 2023
1ea39bc
Merge branch 'main' into webview-scroll-listener
TheVinhLuong Apr 29, 2023
e6a5c55
Resolve conflict
TheVinhLuong Apr 29, 2023
024e3a7
Fixup based on code review
TheVinhLuong Apr 29, 2023
af3358b
Merge branch 'main' into webview-scroll-listener
TheVinhLuong May 30, 2023
c7b5231
Make dart low-level code for offset changes listener mirror the Andro…
TheVinhLuong May 30, 2023
44ca259
Add iOS implementation
TheVinhLuong Jul 3, 2023
726d1a8
Merge branch 'main' into webview-scroll-listener
TheVinhLuong Aug 1, 2023
ac8eacc
Add iOS related unit test codes
TheVinhLuong Aug 1, 2023
59fa39d
Merge branch 'main' into webview-scroll-listener
TheVinhLuong Aug 1, 2023
cfbdee9
Fix CI failing checks
TheVinhLuong Aug 1, 2023
f24f661
Merge branch 'main' into webview-scroll-listener
TheVinhLuong Aug 6, 2023
562bd04
Apply changes based on review comments
TheVinhLuong Aug 27, 2023
1b5e9d3
Merge branch 'main' into webview-scroll-listener
TheVinhLuong Aug 27, 2023
d256a35
Fix code based on code review
TheVinhLuong Sep 26, 2023
df20af9
Merge branch 'main' into webview-scroll-listener
TheVinhLuong Sep 26, 2023
3c2a2ca
Merge branch 'main' into webview-scroll-listener
TheVinhLuong Sep 30, 2023
0c6aac1
Merge branch 'main' of github.com:flutter/packages into webview-scrol…
bparrishMines Oct 3, 2023
ac9dcee
some improvements
bparrishMines Oct 5, 2023
5dfa5b2
switch to doubles
bparrishMines Oct 5, 2023
94eed4b
update webview_flutter
bparrishMines Oct 5, 2023
b0153f9
formatting
bparrishMines Oct 5, 2023
a37dc83
Merge branch 'main' of github.com:flutter/packages into webview-scrol…
bparrishMines Oct 5, 2023
4348c1b
pubspec ordering and doc
bparrishMines Oct 5, 2023
48aa520
Merge branch 'main' of github.com:flutter/packages into webview-scrol…
bparrishMines Oct 11, 2023
02a4758
PR feedback
bparrishMines Oct 11, 2023
1233235
Fix integration test
TheVinhLuong Oct 14, 2023
2c39f56
Merge branch 'main' of github.com:flutter/packages into webview-scrol…
bparrishMines Nov 7, 2023
79e6c2c
Merge branch 'main' into webview-scroll-listener
TheVinhLuong Dec 12, 2023
0d8668b
Merge branch 'main' into webview-scroll-listener
TheVinhLuong Feb 9, 2024
a2400d2
Updates minimum supported SDK version to Flutter 3.16.6/Dart 3.2.3. U…
TheVinhLuong Feb 9, 2024
7f8d4c6
Fixup based on code review
TheVinhLuong Feb 9, 2024
3ea68d8
Merge branch 'main' into webview-scroll-listener
TheVinhLuong Feb 9, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/webview_flutter/webview_flutter_android/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 3.4.5

* Added `setOnContentOffsetChanged` method to the `AndroidWebViewController`.

## 3.4.4

* Fixes a bug where the native `WebView` wouldn't be traversed for autofill automatically.
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
import androidx.annotation.VisibleForTesting;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugins.webviewflutter.GeneratedAndroidWebView.WebViewFlutterApi;
import java.util.Objects;

/**
* Flutter API implementation for `WebView`.
Expand Down Expand Up @@ -56,4 +57,20 @@ public void create(@NonNull WebView instance, @NonNull WebViewFlutterApi.Reply<V
void setApi(@NonNull WebViewFlutterApi api) {
this.api = api;
}

public void onScrollChanged(
@NonNull WebView instance,
@NonNull Long xArg,
@NonNull Long yArg,
@NonNull Long oldXArg,
@NonNull Long oldYArg,
WebViewFlutterApi.Reply<Void> callback) {
api.onScrollPosChange(
Objects.requireNonNull(instanceManager.getIdentifierForStrongReference(instance)),
xArg,
yArg,
oldXArg,
oldYArg,
callback);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ public void setWebContentsDebuggingEnabled(boolean enabled) {
public static class WebViewPlatformView extends WebView implements PlatformView {
private WebViewClient currentWebViewClient;
private WebChromeClientHostApiImpl.SecureWebChromeClient currentWebChromeClient;
private final WebViewFlutterApiImpl webViewFlutterApi;

/**
* Creates a {@link WebViewPlatformView}.
Expand All @@ -94,7 +95,7 @@ public WebViewPlatformView(
super(context);
currentWebViewClient = new WebViewClient();
currentWebChromeClient = new WebChromeClientHostApiImpl.SecureWebChromeClient();

webViewFlutterApi = new WebViewFlutterApiImpl(binaryMessenger, instanceManager);
setWebViewClient(currentWebViewClient);
setWebChromeClient(currentWebChromeClient);
}
Expand Down Expand Up @@ -161,6 +162,13 @@ public void setWebChromeClient(WebChromeClient client) {
public WebChromeClient getWebChromeClient() {
return currentWebChromeClient;
}

@Override
protected void onScrollChanged(int l, int t, int oldL, int oldT) {
super.onScrollChanged(l, t, oldL, oldT);
webViewFlutterApi.onScrollChanged(
this, (long) l, (long) t, (long) oldL, (long) oldT, reply -> {});
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -355,4 +355,25 @@ public void setImportantForAutofillForParentFlutterView() {

verify(mockFlutterView).setImportantForAutofill(View.IMPORTANT_FOR_AUTOFILL_YES);
}

@Test
public void onScrollPosChange() {
final InstanceManager instanceManager = InstanceManager.open(identifier -> {});

final WebViewFlutterApiImpl flutterApiImpl =
new WebViewFlutterApiImpl(mockBinaryMessenger, instanceManager);

final WebViewFlutterApi mockFlutterApi = mock(WebViewFlutterApi.class);
flutterApiImpl.setApi(mockFlutterApi);
flutterApiImpl.create(mockWebView, reply -> {});

flutterApiImpl.onScrollChanged(mockWebView, 0L, 1L, 2L, 3L, reply -> {});

final long instanceIdentifier =
Objects.requireNonNull(instanceManager.getIdentifierForStrongReference(mockWebView));
verify(mockFlutterApi)
.onScrollPosChange(eq(instanceIdentifier), eq(0L), eq(1L), eq(2L), eq(3L), any());

instanceManager.close();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ subprojects {
project.evaluationDependsOn(':app')
}

task clean(type: Delete) {
tasks.register("clean", Delete) {
delete rootProject.buildDir
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -657,7 +657,8 @@ Future<void> main() async {
});

group('Programmatic Scroll', () {
testWidgets('setAndGetScrollPosition', (WidgetTester tester) async {
testWidgets('setAndGetAndListenScrollPosition',
(WidgetTester tester) async {
const String scrollTestPage = '''
<!DOCTYPE html>
<html>
Expand All @@ -683,6 +684,7 @@ Future<void> main() async {
base64Encode(const Utf8Encoder().convert(scrollTestPage));

final Completer<void> pageLoaded = Completer<void>();
Completer<List<int>> offsetsCompleter = Completer<List<int>>();
final PlatformWebViewController controller = PlatformWebViewController(
const PlatformWebViewControllerCreationParams(),
)
Expand All @@ -698,7 +700,11 @@ Future<void> main() async {
'data:text/html;charset=utf-8;base64,$scrollTestPageBase64',
),
),
);
)
..setOnContentOffsetChanged(
(int left, int top, int oldLeft, int oldTop) {
offsetsCompleter.complete(<int>[left, top, oldLeft, oldTop]);
});

await tester.pumpWidget(Builder(
builder: (BuildContext context) {
Expand Down Expand Up @@ -727,12 +733,17 @@ Future<void> main() async {
scrollPos = await controller.getScrollPosition();
expect(scrollPos.dx, X_SCROLL);
expect(scrollPos.dy, Y_SCROLL);
expect(
offsetsCompleter.future, completion(<int>[X_SCROLL, Y_SCROLL, 0, 0]));

// Check scrollBy() (on top of scrollTo())
offsetsCompleter = Completer<List<int>>();
await controller.scrollBy(X_SCROLL, Y_SCROLL);
scrollPos = await controller.getScrollPosition();
expect(scrollPos.dx, X_SCROLL * 2);
expect(scrollPos.dy, Y_SCROLL * 2);
expect(offsetsCompleter.future,
completion(<int>[X_SCROLL * 2, Y_SCROLL * 2, X_SCROLL, Y_SCROLL]));
});
});

Expand Down Expand Up @@ -1124,6 +1135,22 @@ Future<void> main() async {
);
},
);

// testWidgets('On Content Offset Listener', (WidgetTester tester) async {
// final PlatformWebViewController controller = PlatformWebViewController(
// const PlatformWebViewControllerCreationParams(),
// );
// final Completer<List<int>> offsetCompleter = Completer<List<int>>();
// controller.setOnContentOffsetChanged((left, top, oldLeft, oldTop) {
// offsetCompleter.complete([left, top, oldLeft, oldTop]);
// });
//
// await tester.pumpWidget(widget);
//
// await controller.runJavaScript('Echo.postMessage("hello");');
// await expectLater(channelCompleter.future, completion('hello'));
//
// });
}

/// Returns the value used for the HTTP User-Agent: request header in subsequent HTTP requests.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,11 @@ Page resource error:
))
..loadRequest(LoadRequestParams(
uri: Uri.parse('https://flutter.dev'),
));
))
..setOnContentOffsetChanged((int left, int top, int oldLeft, int oldTop) {
debugPrint(
'Scroll offset change to left = $left y = $top oldX = $oldLeft oldY = $oldTop');
});
}

@override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,9 @@ flutter:
- assets/sample_video.mp4
- assets/www/index.html
- assets/www/styles/style.css


# FOR TESTING ONLY. DO NOT MERGE.
dependency_overrides:
webview_flutter_platform_interface:
path: ../../../webview_flutter/webview_flutter_platform_interface
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ class AndroidWebViewProxy {
/// Due to changes in Flutter 3.0 the [useHybridComposition] doesn't have
/// any effect and should not be exposed publicly. More info here:
/// https://github.com/flutter/flutter/issues/108106
final android_webview.WebView Function({
required bool useHybridComposition,
}) createAndroidWebView;
final android_webview.WebView Function(
{required bool useHybridComposition,
required Function(int left, int top, int oldLeft, int oldTop)?
onScrollChanged}) createAndroidWebView;

/// Constructs a [android_webview.WebChromeClient].
final android_webview.WebChromeClient Function({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ class WebView extends JavaObject {
/// https://github.com/flutter/flutter/issues/108106
WebView({
this.useHybridComposition = false,
this.onScrollChanged,
@visibleForTesting super.binaryMessenger,
@visibleForTesting super.instanceManager,
}) : super.detached() {
Expand All @@ -103,6 +104,7 @@ class WebView extends JavaObject {
@protected
WebView.detached({
this.useHybridComposition = false,
this.onScrollChanged,
super.binaryMessenger,
super.instanceManager,
}) : super.detached();
Expand All @@ -125,6 +127,9 @@ class WebView extends JavaObject {
/// The [WebSettings] object used to control the settings for this WebView.
late final WebSettings settings = WebSettings(this);

/// The [ScrollChangedCallback] object used to listen for scroll changed events.
final Function(int left, int top, int oldLeft, int oldTop)? onScrollChanged;

/// Enables debugging of web contents (HTML / CSS / JavaScript) loaded into any WebViews of this application.
///
/// This flag can be enabled in order to facilitate debugging of web layouts
Expand Down Expand Up @@ -414,6 +419,7 @@ class WebView extends JavaObject {
WebView copy() {
return WebView.detached(
useHybridComposition: useHybridComposition,
onScrollChanged: onScrollChanged,
binaryMessenger: _api.binaryMessenger,
instanceManager: _api.instanceManager,
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Autogenerated from Pigeon (v9.0.4), do not edit directly.
// Autogenerated from Pigeon (v9.1.4), do not edit directly.
// See also: https://pub.dev/packages/pigeon
// ignore_for_file: public_member_api_docs, non_constant_identifier_names, avoid_as, unused_import, unnecessary_parenthesis, prefer_null_aware_operators, omit_local_variable_types, unused_shown_name, unnecessary_import

Expand Down Expand Up @@ -993,6 +993,9 @@ abstract class WebViewFlutterApi {
/// Create a new Dart instance and add it to the `InstanceManager`.
void create(int identifier);

void onScrollPosChange(
int webViewInstanceId, int x, int y, int oldX, int oldY);

static void setup(WebViewFlutterApi? api,
{BinaryMessenger? binaryMessenger}) {
{
Expand All @@ -1014,6 +1017,38 @@ abstract class WebViewFlutterApi {
});
}
}
{
final BasicMessageChannel<Object?> channel = BasicMessageChannel<Object?>(
'dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange', codec,
binaryMessenger: binaryMessenger);
if (api == null) {
channel.setMessageHandler(null);
} else {
channel.setMessageHandler((Object? message) async {
assert(message != null,
'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null.');
final List<Object?> args = (message as List<Object?>?)!;
final int? arg_webViewInstanceId = (args[0] as int?);
assert(arg_webViewInstanceId != null,
'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null, expected non-null int.');
final int? arg_x = (args[1] as int?);
assert(arg_x != null,
'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null, expected non-null int.');
final int? arg_y = (args[2] as int?);
assert(arg_y != null,
'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null, expected non-null int.');
final int? arg_oldX = (args[3] as int?);
assert(arg_oldX != null,
'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null, expected non-null int.');
final int? arg_oldY = (args[4] as int?);
assert(arg_oldY != null,
'Argument for dev.flutter.pigeon.WebViewFlutterApi.onScrollPosChange was null, expected non-null int.');
api.onScrollPosChange(
arg_webViewInstanceId!, arg_x!, arg_y!, arg_oldX!, arg_oldY!);
return;
});
}
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class AndroidWebViewFlutterApis {
WebChromeClientFlutterApiImpl? webChromeClientFlutterApi,
JavaScriptChannelFlutterApiImpl? javaScriptChannelFlutterApi,
FileChooserParamsFlutterApiImpl? fileChooserParamsFlutterApi,
WebViewFlutterApiImpl? webViewFlutterApi,
}) {
this.javaObjectFlutterApi =
javaObjectFlutterApi ?? JavaObjectFlutterApiImpl();
Expand All @@ -58,6 +59,7 @@ class AndroidWebViewFlutterApis {
javaScriptChannelFlutterApi ?? JavaScriptChannelFlutterApiImpl();
this.fileChooserParamsFlutterApi =
fileChooserParamsFlutterApi ?? FileChooserParamsFlutterApiImpl();
this.webViewFlutterApi = webViewFlutterApi ?? WebViewFlutterApiImpl();
}

static bool _haveBeenSetUp = false;
Expand Down Expand Up @@ -85,6 +87,9 @@ class AndroidWebViewFlutterApis {
/// Flutter Api for [FileChooserParams].
late final FileChooserParamsFlutterApiImpl fileChooserParamsFlutterApi;

/// Flutter Api for [ScrollListener].
late final WebViewFlutterApiImpl webViewFlutterApi;

/// Ensures all the Flutter APIs have been setup to receive calls from native code.
void ensureSetUp() {
if (!_haveBeenSetUp) {
Expand All @@ -94,6 +99,7 @@ class AndroidWebViewFlutterApis {
WebChromeClientFlutterApi.setup(webChromeClientFlutterApi);
JavaScriptChannelFlutterApi.setup(javaScriptChannelFlutterApi);
FileChooserParamsFlutterApi.setup(fileChooserParamsFlutterApi);
WebViewFlutterApi.setup(webViewFlutterApi);
_haveBeenSetUp = true;
}
}
Expand Down Expand Up @@ -371,6 +377,18 @@ class WebViewFlutterApiImpl implements WebViewFlutterApi {
void create(int identifier) {
instanceManager.addHostCreatedInstance(WebView.detached(), identifier);
}

@override
void onScrollPosChange(
int webViewInstanceId, int x, int y, int oldX, int oldY) {
final WebView? webViewInstance = instanceManager
.getInstanceWithWeakReference(webViewInstanceId) as WebView?;
assert(
webViewInstance != null,
'InstanceManager does not contain a WebView with instanceId: $webViewInstanceId',
);
webViewInstance!.onScrollChanged!(x, y, oldX, oldY);
}
}

/// Host api implementation for [WebSettings].
Expand Down
Loading