[webview_flutter] always make sure the contentInset or the sum of contentInset and adjustedContentInset is 0 on iOS. (#2466)
diff --git a/packages/webview_flutter/CHANGELOG.md b/packages/webview_flutter/CHANGELOG.md
index 32ccc7c..f87091e 100644
--- a/packages/webview_flutter/CHANGELOG.md
+++ b/packages/webview_flutter/CHANGELOG.md
@@ -1,3 +1,8 @@
+## 0.3.19+5
+
+* On iOS, always keep contentInsets of the WebView to be 0.
+* Fix XCTest case to follow XCTest naming convention.
+
## 0.3.19+4
* On iOS, fix the scroll view content inset is automatically adjusted. After the fix, the content position of the WebView is customizable by Flutter.
diff --git a/packages/webview_flutter/ios/Classes/FlutterWebView.h b/packages/webview_flutter/ios/Classes/FlutterWebView.h
index 08e6b8a..6277901 100644
--- a/packages/webview_flutter/ios/Classes/FlutterWebView.h
+++ b/packages/webview_flutter/ios/Classes/FlutterWebView.h
@@ -21,4 +21,12 @@
- (instancetype)initWithMessenger:(NSObject<FlutterBinaryMessenger>*)messenger;
@end
+/**
+ * The WkWebView used for the plugin.
+ *
+ * This class overrides some methods in `WKWebView` to serve the needs for the plugin.
+ */
+@interface FLTWKWebView : WKWebView
+@end
+
NS_ASSUME_NONNULL_END
diff --git a/packages/webview_flutter/ios/Classes/FlutterWebView.m b/packages/webview_flutter/ios/Classes/FlutterWebView.m
index b1fc143..20aad2c 100644
--- a/packages/webview_flutter/ios/Classes/FlutterWebView.m
+++ b/packages/webview_flutter/ios/Classes/FlutterWebView.m
@@ -34,8 +34,30 @@
@end
+@implementation FLTWKWebView
+
+- (void)setFrame:(CGRect)frame {
+ [super setFrame:frame];
+ self.scrollView.contentInset = UIEdgeInsetsZero;
+ // We don't want the contentInsets to be adjusted by iOS, flutter should always take control of
+ // webview's contentInsets.
+ // self.scrollView.contentInset = UIEdgeInsetsZero;
+ if (@available(iOS 11, *)) {
+ // Above iOS 11, adjust contentInset to compensate the adjustedContentInset so the sum will
+ // always be 0.
+ if (UIEdgeInsetsEqualToEdgeInsets(self.scrollView.adjustedContentInset, UIEdgeInsetsZero)) {
+ return;
+ }
+ UIEdgeInsets insetToAdjust = self.scrollView.adjustedContentInset;
+ self.scrollView.contentInset = UIEdgeInsetsMake(-insetToAdjust.top, -insetToAdjust.left,
+ -insetToAdjust.bottom, -insetToAdjust.right);
+ }
+}
+
+@end
+
@implementation FLTWebViewController {
- WKWebView* _webView;
+ FLTWKWebView* _webView;
int64_t _viewId;
FlutterMethodChannel* _channel;
NSString* _currentUrl;
@@ -69,7 +91,7 @@
[self updateAutoMediaPlaybackPolicy:args[@"autoMediaPlaybackPolicy"]
inConfiguration:configuration];
- _webView = [[WKWebView alloc] initWithFrame:frame configuration:configuration];
+ _webView = [[FLTWKWebView alloc] initWithFrame:frame configuration:configuration];
_navigationDelegate = [[FLTWKNavigationDelegate alloc] initWithChannel:_channel];
_webView.navigationDelegate = _navigationDelegate;
__weak __typeof__(self) weakSelf = self;
diff --git a/packages/webview_flutter/ios/Tests/FLTWebViewTests.m b/packages/webview_flutter/ios/Tests/FLTWebViewTests.m
index a545fd7..45fa521 100644
--- a/packages/webview_flutter/ios/Tests/FLTWebViewTests.m
+++ b/packages/webview_flutter/ios/Tests/FLTWebViewTests.m
@@ -7,6 +7,8 @@
@import XCTest;
@import webview_flutter;
+static bool feq(CGFloat a, CGFloat b) { return fabs(b - a) < FLT_EPSILON; }
+
@interface FLTWebViewTests : XCTestCase
@property(strong, nonatomic) NSObject<FlutterBinaryMessenger> *mockBinaryMessenger;
@@ -20,7 +22,7 @@
self.mockBinaryMessenger = OCMProtocolMock(@protocol(FlutterBinaryMessenger));
}
-- (void)canInitFLTWebViewController {
+- (void)testCanInitFLTWebViewController {
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
viewIdentifier:1
@@ -29,7 +31,7 @@
XCTAssertNotNil(controller);
}
-- (void)canInitFLTWebViewFactory {
+- (void)testCanInitFLTWebViewFactory {
FLTWebViewFactory *factory =
[[FLTWebViewFactory alloc] initWithMessenger:self.mockBinaryMessenger];
XCTAssertNotNil(factory);
@@ -50,7 +52,7 @@
}
}
-- (void)webViewScrollIndicatorAticautomaticallyAdjustsScrollIndicatorInsetsShouldbeNoOnIOS13 {
+- (void)testWebViewScrollIndicatorAticautomaticallyAdjustsScrollIndicatorInsetsShouldbeNoOnIOS13 {
if (@available(iOS 13, *)) {
FLTWebViewController *controller =
[[FLTWebViewController alloc] initWithFrame:CGRectMake(0, 0, 300, 400)
@@ -64,4 +66,24 @@
}
}
+- (void)testContentInsetsSumAlwaysZeroAfterSetFrame {
+ FLTWKWebView *webView = [[FLTWKWebView alloc] initWithFrame:CGRectMake(0, 0, 300, 400)];
+ webView.scrollView.contentInset = UIEdgeInsetsMake(0, 0, 300, 0);
+ XCTAssertFalse(UIEdgeInsetsEqualToEdgeInsets(webView.scrollView.contentInset, UIEdgeInsetsZero));
+ webView.frame = CGRectMake(0, 0, 300, 200);
+ XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(webView.scrollView.contentInset, UIEdgeInsetsZero));
+ XCTAssertTrue(CGRectEqualToRect(webView.frame, CGRectMake(0, 0, 300, 200)));
+
+ if (@available(iOS 11, *)) {
+ // After iOS 11, we need to make sure the contentInset compensates the adjustedContentInset.
+ UIScrollView *partialMockScrollView = OCMPartialMock(webView.scrollView);
+ UIEdgeInsets insetToAdjust = UIEdgeInsetsMake(0, 0, 300, 0);
+ OCMStub(partialMockScrollView.adjustedContentInset).andReturn(insetToAdjust);
+ XCTAssertTrue(UIEdgeInsetsEqualToEdgeInsets(webView.scrollView.contentInset, UIEdgeInsetsZero));
+ webView.frame = CGRectMake(0, 0, 300, 100);
+ XCTAssertTrue(feq(webView.scrollView.contentInset.bottom, -insetToAdjust.bottom));
+ XCTAssertTrue(CGRectEqualToRect(webView.frame, CGRectMake(0, 0, 300, 100)));
+ }
+}
+
@end
diff --git a/packages/webview_flutter/pubspec.yaml b/packages/webview_flutter/pubspec.yaml
index e528e8d..bbe6107 100644
--- a/packages/webview_flutter/pubspec.yaml
+++ b/packages/webview_flutter/pubspec.yaml
@@ -1,6 +1,6 @@
name: webview_flutter
description: A Flutter plugin that provides a WebView widget on Android and iOS.
-version: 0.3.19+4
+version: 0.3.19+5
homepage: https://github.com/flutter/plugins/tree/master/packages/webview_flutter
environment: