Skip to content
This repository was archived by the owner on Feb 22, 2023. It is now read-only.

[webview_flutter] Add support for onProgressChanged event #2415

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.3.18+2

* Add support for onProgressChanged event.

## 0.3.18+1

* Be explicit that keyboard is not ready for production in README.md.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.flutter.plugins.webviewflutter;

import android.webkit.WebChromeClient;
import android.webkit.WebView;

import io.flutter.plugin.common.MethodChannel;

public class FlutterWebChromeClient extends WebChromeClient {
private MethodChannel channel;

public FlutterWebChromeClient(MethodChannel channel) {
this.channel = channel;
}

@Override
public void onProgressChanged(WebView view, int newProgress) {
super.onProgressChanged(view, newProgress);
channel.invokeMethod("onProgressChanged", newProgress);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ public class FlutterWebView implements PlatformView, MethodCallHandler {
flutterWebViewClient = new FlutterWebViewClient(methodChannel);
applySettings((Map<String, Object>) params.get("settings"));

webView.setWebChromeClient(new FlutterWebChromeClient(methodChannel));

if (params.containsKey(JS_CHANNEL_NAMES_FIELD)) {
registerJavaScriptChannelNames((List<String>) params.get(JS_CHANNEL_NAMES_FIELD));
}
Expand Down
70 changes: 44 additions & 26 deletions packages/webview_flutter/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class WebViewExample extends StatefulWidget {
class _WebViewExampleState extends State<WebViewExample> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();

double progress = 0.0;
@override
Widget build(BuildContext context) {
return Scaffold(
Expand All @@ -49,31 +49,49 @@ class _WebViewExampleState extends State<WebViewExample> {
// We're using a Builder here so we have a context that is below the Scaffold
// to allow calling Scaffold.of(context) so we can show a snackbar.
body: Builder(builder: (BuildContext context) {
return WebView(
initialUrl: 'https://flutter.dev',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
// TODO(iskakaushik): Remove this when collection literals makes it to stable.
// ignore: prefer_collection_literals
javascriptChannels: <JavascriptChannel>[
_toasterJavascriptChannel(context),
].toSet(),
navigationDelegate: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
print('blocking navigation to $request}');
return NavigationDecision.prevent;
}
print('allowing navigation to $request');
return NavigationDecision.navigate;
},
onPageStarted: (String url) {
print('Page started loading: $url');
},
onPageFinished: (String url) {
print('Page finished loading: $url');
},
return Stack(
children: <Widget>[
WebView(
initialUrl: 'https://flutter.dev',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
// TODO(iskakaushik): Remove this when collection literals makes it to stable.
// ignore: prefer_collection_literals
javascriptChannels: <JavascriptChannel>[
_toasterJavascriptChannel(context),
].toSet(),
navigationDelegate: (NavigationRequest request) {
if (request.url.startsWith('https://www.youtube.com/')) {
print('blocking navigation to $request}');
return NavigationDecision.prevent;
}
print('allowing navigation to $request');
return NavigationDecision.navigate;
},
onPageStarted: (String url) {
print('Page started loading: $url');
},
onPageFinished: (String url) {
print('Page finished loading: $url');
},
onProgressChanged: (int p){
setState(() {
progress = p/100.0;
});
},
),
Offstage(
offstage: progress == 1,
child: SizedBox(
height: 1.5,
child: LinearProgressIndicator(
value: progress,
valueColor: const AlwaysStoppedAnimation(Colors.red),
),
))
],
);
}),
floatingActionButton: favoriteButton(),
Expand Down
15 changes: 15 additions & 0 deletions packages/webview_flutter/ios/Classes/FlutterWebView.m
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ - (instancetype)initWithFrame:(CGRect)frame
[weakSelf onMethodCall:call result:result];
}];

[_webView addObserver:self forKeyPath:@"estimatedProgress" options:NSKeyValueObservingOptionNew context:nil];

[self applySettings:settings];
// TODO(amirh): return an error if apply settings failed once it's possible to do so.
// https://github.com/flutter/flutter/issues/36228
Expand All @@ -88,7 +90,20 @@ - (instancetype)initWithFrame:(CGRect)frame
}
return self;
}
#pragma mark - listen estimatedProgress
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {

if ([keyPath isEqualToString:@"estimatedProgress"]) {
if (object == _webView) {
int progress =(int)(_webView.estimatedProgress*100);
[_channel invokeMethod:@"onProgressChanged" arguments: [NSNumber numberWithInt:progress]];
}
}
}

- (void)dealloc {
[_webView removeObserver:self forKeyPath:@"estimatedProgress"];
}
- (UIView*)view {
return _webView;
}
Expand Down
3 changes: 3 additions & 0 deletions packages/webview_flutter/lib/platform_interface.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ abstract class WebViewPlatformCallbacksHandler {

/// Invoked by [WebViewPlatformController] when a page has finished loading.
void onPageFinished(String url);

/// Invoked by [WebViewPlatformController] when a page is loading in progress.
void onProgressChanged(int progress);
}

/// Interface for talking to the webview's platform implementation.
Expand Down
3 changes: 3 additions & 0 deletions packages/webview_flutter/lib/src/webview_method_channel.dart
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@ class MethodChannelWebViewPlatform implements WebViewPlatformController {
case 'onPageStarted':
_platformCallbacksHandler.onPageStarted(call.arguments['url']);
return null;
case 'onProgressChanged':
_platformCallbacksHandler.onProgressChanged(call.arguments);
return null;
}
throw MissingPluginException(
'${call.method} was invoked but has no handler');
Expand Down
15 changes: 15 additions & 0 deletions packages/webview_flutter/lib/webview_flutter.dart
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ typedef void PageStartedCallback(String url);
/// Signature for when a [WebView] has finished loading a page.
typedef void PageFinishedCallback(String url);

/// Signature for when a [WebView] is loading in progress.
typedef void OnProgressChangedCallback(int progress);

/// Specifies possible restrictions on automatic media playback.
///
/// This is typically used in [WebView.initialMediaPlaybackPolicy].
Expand Down Expand Up @@ -147,6 +150,7 @@ class WebView extends StatefulWidget {
this.gestureRecognizers,
this.onPageStarted,
this.onPageFinished,
this.onProgressChanged,
this.debuggingEnabled = false,
this.userAgent,
this.initialMediaPlaybackPolicy =
Expand Down Expand Up @@ -276,6 +280,10 @@ class WebView extends StatefulWidget {
/// [WebViewController.evaluateJavascript] can assume this.
final PageFinishedCallback onPageFinished;


/// Invoked when a page is loading in progress.
final OnProgressChangedCallback onProgressChanged;

/// Controls whether WebView debugging is enabled.
///
/// Setting this to true enables [WebView debugging on Android](https://developers.google.com/web/tools/chrome-devtools/remote-debugging/).
Expand Down Expand Up @@ -473,6 +481,13 @@ class _PlatformCallbacksHandler implements WebViewPlatformCallbacksHandler {
}
}

@override
void onProgressChanged(int progress) {
if (_widget.onProgressChanged != null) {
_widget.onProgressChanged(progress);
}
}

void _updateJavascriptChannelsFromSet(Set<JavascriptChannel> channels) {
_javascriptChannels.clear();
if (channels == null) {
Expand Down
2 changes: 1 addition & 1 deletion packages/webview_flutter/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: webview_flutter
description: A Flutter plugin that provides a WebView widget on Android and iOS.
version: 0.3.18+1
version: 0.3.18+2
homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter

environment:
Expand Down