[webview_flutter] Add a backgroundColor option to the iOS webview (#4570)
This PR add an option to set the background color of the iOS webview.
Part of https://github.com/flutter/plugins/pull/3431
Part of https://github.com/flutter/flutter/issues/29300
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md
index e9c59c2..22f45f2 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md
+++ b/packages/webview_flutter/webview_flutter_wkwebview/CHANGELOG.md
@@ -1,5 +1,6 @@
-## NEXT
+## 2.5.0
+* Adds an option to set the background color of the webview.
* Migrates from `analysis_options_legacy.yaml` to `analysis_options.yaml`.
* Integration test fixes.
* Updates to webview_flutter_platform_interface version 1.5.2.
@@ -22,7 +23,7 @@
## 2.0.14
-* Update example App so navigation menu loads immediatly but only becomes available when `WebViewController` is available (same behavior as example App in webview_flutter package).
+* Update example App so navigation menu loads immediatly but only becomes available when `WebViewController` is available (same behavior as example App in webview_flutter package).
## 2.0.13
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerUITests/FLTWebViewUITests.m b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerUITests/FLTWebViewUITests.m
index d193be7..e43fb97 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerUITests/FLTWebViewUITests.m
+++ b/packages/webview_flutter/webview_flutter_wkwebview/example/ios/RunnerUITests/FLTWebViewUITests.m
@@ -5,6 +5,25 @@
@import XCTest;
@import os.log;
+static UIColor* getPixelColorInImage(CGImageRef image, size_t x, size_t y) {
+ CFDataRef pixelData = CGDataProviderCopyData(CGImageGetDataProvider(image));
+ const UInt8* data = CFDataGetBytePtr(pixelData);
+
+ size_t bytesPerRow = CGImageGetBytesPerRow(image);
+ size_t pixelInfo = (bytesPerRow * y) + (x * 4); // 4 bytes per pixel
+
+ UInt8 red = data[pixelInfo + 0];
+ UInt8 green = data[pixelInfo + 1];
+ UInt8 blue = data[pixelInfo + 2];
+ UInt8 alpha = data[pixelInfo + 3];
+ CFRelease(pixelData);
+
+ return [UIColor colorWithRed:red / 255.0f
+ green:green / 255.0f
+ blue:blue / 255.0f
+ alpha:alpha / 255.0f];
+}
+
@interface FLTWebViewUITests : XCTestCase
@property(nonatomic, strong) XCUIApplication* app;
@end
@@ -18,6 +37,54 @@
[self.app launch];
}
+- (void)testTransparentBackground {
+ XCUIApplication* app = self.app;
+ XCUIElement* menu = app.buttons[@"Show menu"];
+ if (![menu waitForExistenceWithTimeout:30.0]) {
+ os_log_error(OS_LOG_DEFAULT, "%@", app.debugDescription);
+ XCTFail(@"Failed due to not able to find menu");
+ }
+ [menu tap];
+
+ XCUIElement* transparentBackground = app.buttons[@"Transparent background example"];
+ if (![transparentBackground waitForExistenceWithTimeout:30.0]) {
+ os_log_error(OS_LOG_DEFAULT, "%@", app.debugDescription);
+ XCTFail(@"Failed due to not able to find Transparent background example");
+ }
+ [transparentBackground tap];
+
+ XCUIElement* transparentBackgroundLoaded =
+ app.webViews.staticTexts[@"Transparent background test"];
+ if (![transparentBackgroundLoaded waitForExistenceWithTimeout:30.0]) {
+ os_log_error(OS_LOG_DEFAULT, "%@", app.debugDescription);
+ XCTFail(@"Failed due to not able to find Transparent background test");
+ }
+
+ XCUIScreenshot* screenshot = [[XCUIScreen mainScreen] screenshot];
+
+ UIImage* screenshotImage = screenshot.image;
+ CGImageRef screenshotCGImage = screenshotImage.CGImage;
+ UIColor* centerLeftColor =
+ getPixelColorInImage(screenshotCGImage, 0, CGImageGetHeight(screenshotCGImage) / 2);
+ UIColor* centerColor =
+ getPixelColorInImage(screenshotCGImage, CGImageGetWidth(screenshotCGImage) / 2,
+ CGImageGetHeight(screenshotCGImage) / 2);
+
+ CGColorSpaceRef centerLeftColorSpace = CGColorGetColorSpace(centerLeftColor.CGColor);
+ // Flutter Colors.green color : 0xFF4CAF50 -> rgba(76, 175, 80, 1)
+ // https://github.com/flutter/flutter/blob/f4abaa0735eba4dfd8f33f73363911d63931fe03/packages/flutter/lib/src/material/colors.dart#L1208
+ // The background color of the webview is : rgba(0, 0, 0, 0.5)
+ // The expected color is : rgba(38, 87, 40, 1)
+ CGFloat flutterGreenColorComponents[] = {38.0f / 255.0f, 87.0f / 255.0f, 40.0f / 255.0f, 1.0f};
+ CGColorRef flutterGreenColor = CGColorCreate(centerLeftColorSpace, flutterGreenColorComponents);
+ CGFloat redColorComponents[] = {1.0f, 0.0f, 0.0f, 1.0f};
+ CGColorRef redColor = CGColorCreate(centerLeftColorSpace, redColorComponents);
+ CGColorSpaceRelease(centerLeftColorSpace);
+
+ XCTAssertTrue(CGColorEqualToColor(flutterGreenColor, centerLeftColor.CGColor));
+ XCTAssertTrue(CGColorEqualToColor(redColor, centerColor.CGColor));
+}
+
- (void)testUserAgent {
XCUIApplication* app = self.app;
XCUIElement* menu = app.buttons[@"Show menu"];
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart
index df85d42..41297bf 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/main.dart
@@ -37,6 +37,27 @@
</html>
''';
+const String kTransparentBackgroundPage = '''
+<!DOCTYPE html>
+<html>
+<head>
+ <title>Transparent background test</title>
+</head>
+<style type="text/css">
+ body { background: transparent; margin: 0; padding: 0; }
+ #container { position: relative; margin: 0; padding: 0; width: 100vw; height: 100vh; }
+ #shape { background: #FF0000; width: 200px; height: 100%; margin: 0; padding: 0; position: absolute; top: 0; bottom: 0; left: calc(50% - 100px); }
+ p { text-align: center; }
+</style>
+<body>
+ <div id="container">
+ <p>Transparent background test</p>
+ <div id="shape"></div>
+ </div>
+</body>
+</html>
+''';
+
const String kLocalFileExamplePage = '''
<!DOCTYPE html>
<html lang="en">
@@ -47,8 +68,8 @@
<h1>Local demo page</h1>
<p>
- This is an example page used to demonstrate how to load a local file or HTML
- string using the <a href="https://pub.dev/packages/webview_flutter">Flutter
+ This is an example page used to demonstrate how to load a local file or HTML
+ string using the <a href="https://pub.dev/packages/webview_flutter">Flutter
webview</a> plugin.
</p>
@@ -70,6 +91,7 @@
@override
Widget build(BuildContext context) {
return Scaffold(
+ backgroundColor: const Color(0xFF4CAF50),
appBar: AppBar(
title: const Text('Flutter WebView example'),
// This drop down menu demonstrates that Flutter widgets can be shown over the web view.
@@ -96,6 +118,7 @@
print('allowing navigation to $request');
return NavigationDecision.navigate;
},
+ backgroundColor: const Color(0x80000000),
);
}),
floatingActionButton: favoriteButton(),
@@ -146,6 +169,7 @@
loadLocalFile,
loadHtmlString,
doPostRequest,
+ transparentBackground,
}
class _SampleMenu extends StatelessWidget {
@@ -160,6 +184,7 @@
builder:
(BuildContext context, AsyncSnapshot<WebViewController> controller) {
return PopupMenuButton<_MenuOptions>(
+ key: const ValueKey<String>('ShowPopupMenu'),
onSelected: (_MenuOptions value) {
switch (value) {
case _MenuOptions.showUserAgent:
@@ -192,6 +217,9 @@
case _MenuOptions.doPostRequest:
_onDoPostRequest(controller.data!, context);
break;
+ case _MenuOptions.transparentBackground:
+ _onTransparentBackground(controller.data!, context);
+ break;
}
},
itemBuilder: (BuildContext context) => <PopupMenuItem<_MenuOptions>>[
@@ -236,6 +264,11 @@
value: _MenuOptions.doPostRequest,
child: Text('Post Request'),
),
+ const PopupMenuItem<_MenuOptions>(
+ key: ValueKey<String>('ShowTransparentBackgroundExample'),
+ value: _MenuOptions.transparentBackground,
+ child: Text('Transparent background example'),
+ ),
],
);
},
@@ -346,6 +379,11 @@
);
}
+ Future<void> _onTransparentBackground(
+ WebViewController controller, BuildContext context) async {
+ await controller.loadHtmlString(kTransparentBackgroundPage);
+ }
+
static Future<String> _prepareLocalFile() async {
final String tmpDir = (await getTemporaryDirectory()).path;
final File indexFile = File('$tmpDir/www/index.html');
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart
index ae540ae..69fa2bd 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart
+++ b/packages/webview_flutter/webview_flutter_wkwebview/example/lib/web_view.dart
@@ -69,6 +69,7 @@
this.initialMediaPlaybackPolicy =
AutoMediaPlaybackPolicy.require_user_action_for_all_media_types,
this.allowsInlineMediaPlayback = false,
+ this.backgroundColor,
}) : assert(javascriptMode != null),
assert(initialMediaPlaybackPolicy != null),
assert(allowsInlineMediaPlayback != null),
@@ -227,6 +228,12 @@
/// The default policy is [AutoMediaPlaybackPolicy.require_user_action_for_all_media_types].
final AutoMediaPlaybackPolicy initialMediaPlaybackPolicy;
+ /// The background color of the [WebView].
+ ///
+ /// When `null` the platform's webview default background color is used. By
+ /// default [backgroundColor] is `null`.
+ final Color? backgroundColor;
+
@override
_WebViewState createState() => _WebViewState();
}
@@ -278,6 +285,7 @@
_javascriptChannelRegistry.channels.keys.toSet(),
autoMediaPlaybackPolicy: widget.initialMediaPlaybackPolicy,
userAgent: widget.userAgent,
+ backgroundColor: widget.backgroundColor,
),
javascriptChannelRegistry: _javascriptChannelRegistry,
);
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/example/pubspec.yaml
index 2888cdd..2070b11 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 @@
sdk: flutter
path_provider: ^2.0.6
-
+
webview_flutter_wkwebview:
# When depending on this package from a real application you should use:
# webview_flutter: ^x.y.z
@@ -34,4 +34,3 @@
assets:
- assets/sample_audio.ogg
- assets/sample_video.mp4
-
\ No newline at end of file
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m
index 351d1ae..25a93a6 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m
+++ b/packages/webview_flutter/webview_flutter_wkwebview/ios/Classes/FlutterWebView.m
@@ -96,6 +96,20 @@
inConfiguration:configuration];
_webView = [[FLTWKWebView alloc] initWithFrame:frame configuration:configuration];
+
+ // Background color
+ NSNumber* backgroundColorNSNumber = args[@"backgroundColor"];
+ if ([backgroundColorNSNumber isKindOfClass:[NSNumber class]]) {
+ int backgroundColorInt = [backgroundColorNSNumber intValue];
+ UIColor* backgroundColor = [UIColor colorWithRed:(backgroundColorInt >> 16 & 0xff) / 255.0
+ green:(backgroundColorInt >> 8 & 0xff) / 255.0
+ blue:(backgroundColorInt & 0xff) / 255.0
+ alpha:(backgroundColorInt >> 24 & 0xff) / 255.0];
+ _webView.opaque = NO;
+ _webView.backgroundColor = UIColor.clearColor;
+ _webView.scrollView.backgroundColor = backgroundColor;
+ }
+
_navigationDelegate = [[FLTWKNavigationDelegate alloc] initWithChannel:_channel];
_webView.UIDelegate = self;
_webView.navigationDelegate = _navigationDelegate;
diff --git a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml
index a152e2b..7024733 100644
--- a/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml
+++ b/packages/webview_flutter/webview_flutter_wkwebview/pubspec.yaml
@@ -2,7 +2,7 @@
description: A Flutter plugin that provides a WebView widget based on Apple's WKWebView control.
repository: https://github.com/flutter/plugins/tree/master/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: 2.4.0
+version: 2.5.0
environment:
sdk: ">=2.14.0 <3.0.0"
@@ -18,11 +18,11 @@
dependencies:
flutter:
sdk: flutter
- webview_flutter_platform_interface: ^1.5.2
+ webview_flutter_platform_interface: ^1.7.0
dev_dependencies:
flutter_driver:
sdk: flutter
flutter_test:
sdk: flutter
- pedantic: ^1.10.0
\ No newline at end of file
+ pedantic: ^1.10.0