From bcc5fc68ba201fab77f9217f7b9e546032fdba94 Mon Sep 17 00:00:00 2001 From: Lorenzo Pichilli Date: Sat, 13 Mar 2021 15:24:31 +0100 Subject: [PATCH] fix #719, Fixed iOS sometimes scrollView.contentSize doesn't fit all the frame.size available, Added canScrollVertically and canScrollHorizontally webview methods --- .github/no-response.yml | 2 +- CHANGELOG.md | 5 ++- .../InAppWebViewMethodHandler.java | 14 ++++++++ .../in_app_webview/InAppWebView.java | 36 ++++++++++++++++--- .../pull_to_refresh/PullToRefreshLayout.java | 6 ++++ example/.flutter-plugins-dependencies | 2 +- .../ios/Flutter/flutter_export_environment.sh | 5 +-- ios/Classes/InAppWebView/InAppWebView.swift | 16 +++++++++ ios/Classes/InAppWebViewMethodHandler.swift | 16 ++++++++- .../WebMessageListenerJS.swift | 4 +-- .../in_app_webview_controller.dart | 10 ++++++ 11 files changed, 103 insertions(+), 13 deletions(-) diff --git a/.github/no-response.yml b/.github/no-response.yml index 29aa524d..b5ced482 100644 --- a/.github/no-response.yml +++ b/.github/no-response.yml @@ -1,7 +1,7 @@ # Configuration for probot-no-response - https://github.com/probot/no-response # Number of days of inactivity before an Issue is closed for lack of response -daysUntilClose: 7 +daysUntilClose: 5 # Label requiring a response responseRequiredLabel: answered # Comment to post when closing an Issue for lack of response. Set to `false` to disable diff --git a/CHANGELOG.md b/CHANGELOG.md index 2d1d2144..acc28539 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,11 +1,14 @@ ## 5.2.0 - Added `WebMessageChannel` and `WebMessageListener` features -- `AndroidInAppWebViewController.getCurrentWebViewPackage` is available now starting from Android API 21+. +- Added `canScrollVertically` and `canScrollHorizontally` webview methods +- `AndroidInAppWebViewController.getCurrentWebViewPackage` is available now starting from Android API 21+ - Updated Android Gradle distributionUrl version to `5.6.4` - Attempt to fix "InAppBrowserActivity.onCreate NullPointerException - Attempt to invoke virtual method 'java.lang.String android.os.Bundle.getString(java.lang.String)' on a null object reference" [#665](https://github.com/pichillilorenzo/flutter_inappwebview/issues/665) - Fixed "[iOS] Application crashes when processing onCreateWindow" [#579](https://github.com/pichillilorenzo/flutter_inappwebview/issues/579) - Fixed wrong mapping of `NavigationAction` class on Android for `androidHasGesture` and `androidIsRedirect` properties +- Fixed "Pull to refresh creating problem in some webpages on Android" [#719](https://github.com/pichillilorenzo/flutter_inappwebview/issues/719) +- Fixed iOS sometimes `scrollView.contentSize` doesn't fit all the `frame.size` available ## 5.1.0+4 diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewMethodHandler.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewMethodHandler.java index 950eaa98..746ba692 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewMethodHandler.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/InAppWebViewMethodHandler.java @@ -563,6 +563,20 @@ public class InAppWebViewMethodHandler implements MethodChannel.MethodCallHandle result.success(true); } break; + case "canScrollVertically": + if (webView != null) { + result.success(webView.canScrollVertically()); + } else { + result.success(false); + } + break; + case "canScrollHorizontally": + if (webView != null) { + result.success(webView.canScrollHorizontally()); + } else { + result.success(false); + } + break; default: result.notImplemented(); } diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebView.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebView.java index e88e6506..9a34cb75 100755 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebView.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/in_app_webview/InAppWebView.java @@ -9,7 +9,6 @@ import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Point; import android.graphics.drawable.ColorDrawable; -import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; @@ -30,6 +29,7 @@ import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewParent; import android.view.ViewTreeObserver; import android.view.inputmethod.EditorInfo; import android.view.inputmethod.InputConnection; @@ -41,7 +41,6 @@ import android.webkit.WebBackForwardList; import android.webkit.WebHistoryItem; import android.webkit.WebSettings; import android.webkit.WebStorage; -import android.webkit.WebView; import android.widget.HorizontalScrollView; import android.widget.LinearLayout; import android.widget.TextView; @@ -49,8 +48,6 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.annotation.RequiresApi; -import androidx.webkit.JavaScriptReplyProxy; -import androidx.webkit.WebMessageCompat; import androidx.webkit.WebViewCompat; import androidx.webkit.WebViewFeature; @@ -73,6 +70,7 @@ import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.OnWindowFocusE import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.PluginScriptsUtil; import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.PrintJS; import com.pichillilorenzo.flutter_inappwebview.plugin_scripts_js.PromisePolyfillJS; +import com.pichillilorenzo.flutter_inappwebview.pull_to_refresh.PullToRefreshLayout; import com.pichillilorenzo.flutter_inappwebview.types.ContentWorld; import com.pichillilorenzo.flutter_inappwebview.types.PluginScript; import com.pichillilorenzo.flutter_inappwebview.types.PreferredContentModeOptionType; @@ -87,7 +85,6 @@ import org.json.JSONObject; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.ArrayList; -import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; @@ -478,6 +475,22 @@ final public class InAppWebView extends InputAwareWebView { return false; } }); + + getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { + @Override + public void onGlobalLayout() { + final boolean canScrollVertical = canScrollVertically(); + ViewParent parent = getParent(); + if (parent instanceof PullToRefreshLayout) { + PullToRefreshLayout pullToRefreshLayout = (PullToRefreshLayout) parent; + if (!canScrollVertical) { + pullToRefreshLayout.setEnabled(false); + } else { + pullToRefreshLayout.setEnabled(pullToRefreshLayout.options.enabled); + } + } + } + }); } public void setIncognito(boolean enabled) { @@ -1242,6 +1255,11 @@ final public class InAppWebView extends InputAwareWebView { return super.onTouchEvent(ev); } +// @Override +// protected void onOverScrolled(int scrollX, int scrollY, boolean clampedX, boolean clampedY) { +// super.onOverScrolled(scrollX, scrollY, clampedX, clampedY); +// } + @Override public boolean dispatchTouchEvent(MotionEvent event) { return super.dispatchTouchEvent(event); @@ -1592,6 +1610,14 @@ final public class InAppWebView extends InputAwareWebView { } }); } + + public boolean canScrollVertically() { + return computeVerticalScrollRange() > computeVerticalScrollExtent(); + } + + public boolean canScrollHorizontally() { + return computeHorizontalScrollRange() > computeHorizontalScrollExtent(); + } @TargetApi(Build.VERSION_CODES.M) public WebMessageChannel createCompatWebMessageChannel() { diff --git a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/pull_to_refresh/PullToRefreshLayout.java b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/pull_to_refresh/PullToRefreshLayout.java index cec3aa62..c9b5c0df 100644 --- a/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/pull_to_refresh/PullToRefreshLayout.java +++ b/android/src/main/java/com/pichillilorenzo/flutter_inappwebview/pull_to_refresh/PullToRefreshLayout.java @@ -3,11 +3,17 @@ package com.pichillilorenzo.flutter_inappwebview.pull_to_refresh; import android.content.Context; import android.graphics.Color; import android.util.AttributeSet; +import android.util.Log; +import android.view.MotionEvent; +import android.view.View; +import android.webkit.WebView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.swiperefreshlayout.widget.SwipeRefreshLayout; +import com.pichillilorenzo.flutter_inappwebview.R; + import java.util.HashMap; import java.util.Map; diff --git a/example/.flutter-plugins-dependencies b/example/.flutter-plugins-dependencies index bf36e700..f72a8334 100644 --- a/example/.flutter-plugins-dependencies +++ b/example/.flutter-plugins-dependencies @@ -1 +1 @@ -{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-03-11 22:30:27.356562","version":"2.1.0-10.0.pre"} \ No newline at end of file +{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"android":[{"name":"flutter_downloader","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_downloader-1.5.2/","dependencies":[]},{"name":"flutter_inappwebview","path":"/Users/lorenzopichilli/Desktop/flutter_inappwebview/","dependencies":[]},{"name":"integration_test","path":"/Users/lorenzopichilli/flutter/packages/integration_test/","dependencies":[]},{"name":"path_provider","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider-2.0.0-nullsafety/","dependencies":[]},{"name":"permission_handler","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/permission_handler-5.1.0+2/","dependencies":[]},{"name":"url_launcher","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher-6.0.0-nullsafety.6/","dependencies":[]}],"macos":[{"name":"path_provider_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_macos-0.0.5-nullsafety/","dependencies":[]},{"name":"url_launcher_macos","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_macos-0.1.0-nullsafety.2/","dependencies":[]}],"linux":[{"name":"path_provider_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_linux-0.2.0-nullsafety/","dependencies":[]},{"name":"url_launcher_linux","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_linux-0.1.0-nullsafety.3/","dependencies":[]}],"windows":[{"name":"path_provider_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/path_provider_windows-0.1.0-nullsafety.3/","dependencies":[]},{"name":"url_launcher_windows","path":"/Users/lorenzopichilli/flutter/.pub-cache/hosted/pub.dartlang.org/url_launcher_windows-0.1.0-nullsafety.2/","dependencies":[]}],"web":[]},"dependencyGraph":[{"name":"flutter_downloader","dependencies":[]},{"name":"flutter_inappwebview","dependencies":[]},{"name":"integration_test","dependencies":[]},{"name":"path_provider","dependencies":["path_provider_macos","path_provider_linux","path_provider_windows"]},{"name":"path_provider_linux","dependencies":[]},{"name":"path_provider_macos","dependencies":[]},{"name":"path_provider_windows","dependencies":[]},{"name":"permission_handler","dependencies":[]},{"name":"url_launcher","dependencies":["url_launcher_linux","url_launcher_macos","url_launcher_windows"]},{"name":"url_launcher_linux","dependencies":[]},{"name":"url_launcher_macos","dependencies":[]},{"name":"url_launcher_windows","dependencies":[]}],"date_created":"2021-03-13 14:56:36.936663","version":"2.1.0-10.0.pre"} \ No newline at end of file diff --git a/example/ios/Flutter/flutter_export_environment.sh b/example/ios/Flutter/flutter_export_environment.sh index b7fc9f56..ff2151af 100755 --- a/example/ios/Flutter/flutter_export_environment.sh +++ b/example/ios/Flutter/flutter_export_environment.sh @@ -2,12 +2,13 @@ # This is a generated file; do not edit or check into version control. export "FLUTTER_ROOT=/Users/lorenzopichilli/flutter" export "FLUTTER_APPLICATION_PATH=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example" -export "FLUTTER_TARGET=lib/main.dart" +export "FLUTTER_TARGET=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/lib/main.dart" export "FLUTTER_BUILD_DIR=build" export "SYMROOT=${SOURCE_ROOT}/../build/ios" export "FLUTTER_BUILD_NAME=1.0.0" export "FLUTTER_BUILD_NUMBER=1" +export "DART_DEFINES=Zmx1dHRlci5pbnNwZWN0b3Iuc3RydWN0dXJlZEVycm9ycz10cnVl,RkxVVFRFUl9XRUJfQVVUT19ERVRFQ1Q9dHJ1ZQ==" export "DART_OBFUSCATION=false" -export "TRACK_WIDGET_CREATION=false" +export "TRACK_WIDGET_CREATION=true" export "TREE_SHAKE_ICONS=false" export "PACKAGE_CONFIG=/Users/lorenzopichilli/Desktop/flutter_inappwebview/example/.dart_tool/package_config.json" diff --git a/ios/Classes/InAppWebView/InAppWebView.swift b/ios/Classes/InAppWebView/InAppWebView.swift index e51db2b2..c22614fc 100755 --- a/ios/Classes/InAppWebView/InAppWebView.swift +++ b/ios/Classes/InAppWebView/InAppWebView.swift @@ -1542,6 +1542,14 @@ public class InAppWebView: WKWebView, UIScrollViewDelegate, WKUIDelegate, WKNavi InAppWebView.credentialsProposed = [] evaluateJavaScript(PLATFORM_READY_JS_SOURCE, completionHandler: nil) + + // sometimes scrollView.contentSize doesn't fit all the frame.size available + // so, we call setNeedsLayout to redraw the layout + let webViewFrameSize = frame.size + let scrollViewSize = scrollView.contentSize + if (scrollViewSize.width < webViewFrameSize.width || scrollViewSize.height < webViewFrameSize.height) { + setNeedsLayout() + } onLoadStop(url: url?.absoluteString) @@ -2737,6 +2745,14 @@ if(window.\(JAVASCRIPT_BRIDGE_NAME)[\(_callHandlerID)] != null) { } } + public func canScrollVertically() -> Bool { + return scrollView.contentSize.height > self.frame.height + } + + public func canScrollHorizontally() -> Bool { + return scrollView.contentSize.width > self.frame.width + } + public func enablePullToRefresh() { if let pullToRefreshControl = pullToRefreshControl { if #available(iOS 10.0, *) { diff --git a/ios/Classes/InAppWebViewMethodHandler.swift b/ios/Classes/InAppWebViewMethodHandler.swift index 5d416b3a..d65d58aa 100644 --- a/ios/Classes/InAppWebViewMethodHandler.swift +++ b/ios/Classes/InAppWebViewMethodHandler.swift @@ -524,7 +524,21 @@ public class InAppWebViewMethodHandler: FlutterMethodCallDelegate { } else { result(false) } - break + break + case "canScrollVertically": + if let webView = webView { + result(webView.canScrollVertically()) + } else { + result(false) + } + break + case "canScrollHorizontally": + if let webView = webView { + result(webView.canScrollHorizontally()) + } else { + result(false) + } + break default: result(FlutterMethodNotImplemented) break diff --git a/ios/Classes/PluginScriptsJS/WebMessageListenerJS.swift b/ios/Classes/PluginScriptsJS/WebMessageListenerJS.swift index 369ac913..91ff57ea 100644 --- a/ios/Classes/PluginScriptsJS/WebMessageListenerJS.swift +++ b/ios/Classes/PluginScriptsJS/WebMessageListenerJS.swift @@ -101,12 +101,12 @@ window.\(JAVASCRIPT_BRIDGE_NAME)._isOriginAllowed = function(allowedOriginRules, (rule.host[0] === "*" && host != null && host.indexOf(rule.host.split("*")[1]) >= 0) || (hostIPv6 != null && IPv6 != null && hostIPv6 === IPv6); - var portAllowed = rulePort === currentPort + var portAllowed = rulePort === currentPort; if (schemeAllowed && hostAllowed && portAllowed) { return true; } } - return false + return false; } """ diff --git a/lib/src/in_app_webview/in_app_webview_controller.dart b/lib/src/in_app_webview/in_app_webview_controller.dart index 59319230..a3c81e48 100644 --- a/lib/src/in_app_webview/in_app_webview_controller.dart +++ b/lib/src/in_app_webview/in_app_webview_controller.dart @@ -2116,6 +2116,16 @@ class InAppWebViewController { await _channel.invokeMethod('addWebMessageListener', args); } + Future canScrollVertically() async { + Map args = {}; + return await _channel.invokeMethod('canScrollVertically', args); + } + + Future canScrollHorizontally() async { + Map args = {}; + return await _channel.invokeMethod('canScrollHorizontally', args); + } + ///Gets the default user agent. /// ///**Official Android API**: https://developer.android.com/reference/android/webkit/WebSettings#getDefaultUserAgent(android.content.Context)