_From @jibon57 on February 17, 2018 8:42_
Hello,
I am trying to disable to auto zoom of webview by this:
ngAfterViewInit() {
let webview: WebView = this.webViewRef.nativeElement;
webview.on(WebView.loadStartedEvent, function (args: LoadEventData) {
if (webview.android) {
webview.android.getSettings().setLoadWithOverviewMode(true);
webview.android.getSettings().setUseWideViewPort(true);
} else {
webview.ios.scrollView.minimumZoomScale = 1.0;
webview.ios.scrollView.maximumZoomScale = 1.0;
webview.ios.scalesPageToFit = true;
}
})
webview.on(WebView.loadFinishedEvent, function (args: LoadEventData) {
if (webview.ios) {
webview.ios.scrollView.minimumZoomScale = 1.0;
webview.ios.scrollView.maximumZoomScale = 1.0;
webview.ios.scalesPageToFit = true;
}
})
}
following: https://stackoverflow.com/a/21654472
The above solution is working in Android but not in iOS. How can I solve it? Thanks in advance.
_Copied from original issue: NativeScript/ios-runtime#883_
Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.
Hi @jibon57,
For your case, you could try to implement viewForZooming delegate method, which should give you control on the zoom effect of the WebView. More about this topic could be found here
@tsonevn I want to disable initial auto zoom not to disable zoom feature. Will you please share code for nativescript directly?
Hi @jibon57,
The page loaded in the WebView will be loaded in its original size, and there is no need to disable the zoom effect for the initial time.
It would help if you could provide more info about your case as well as a sample project, which could be used for debugging.
@tsonevn Thanks for reply. It was just webview like:
<WebView #webview src="http://www.wonderful-english.com/"></WebView>
Basically that website isn't responsive for mobile. That's fine but in webview it's showing in zoom view. I solved the problem for android by using above code (in first comment) but I can't adjust in iOS.
news about disabling zoom on ios webview?
I also want to disable zooming!
Hi @gimox @jibon57,
I was able to recreate the case; however, I am still looking for an appropriate way to set up the initial scale of the web page
@tsonevn
Here's my solution https://github.com/mxth/NativeScript/commit/d7ae10566ef42f32571f2e691be6bb90f75d6521
you can set the html page's meta, like this:
<meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
Hi!
What news about disabling zoom on ios webview?
Hi, this is an important feature for both ios and android. Any updates? This is very simple in Cordova and should be in NativeScript - it's a frequently used feature.
Has there been any changes with this? I have tried both setDisplayZoomControls="false"
inside the webview and <meta name="viewport" content="width=device-width, initial-scale=1,maximum-scale=1,minimum-scale=1,user-scalable=no">
to no effect. On iOS the page is still zoomable.
@erikandershed? ☝️
bind this javascript in webview. That's enough.
document.addEventListener('gesturestart', function (e) {
e.preventDefault();
});
and for the double tab in ios. Use the following js
var touchtime = 0;
document.addEventListener('touchend', function (e) {
if (touchtime == 0) {
// set first click
touchtime = new Date().getTime();
} else {
// compare first click to this click and see if they occurred within double click threshold
if (((new Date().getTime()) - touchtime) < 800) {
// double click occurred
touchtime = 0;
e.preventDefault();
} else {
// not a double click so set as a new first click
touchtime = new Date().getTime();
}
}
});
@batmanbury If you like to disable user zoom of page you need to do it in NativeScript. Like this:
webView.ios.scrollView.minimumZoomScale = 1.0;
webView.ios.scrollView.maximumZoomScale = 1.0;
webView.ios.scalesPageToFit = false;
const INJECTEDJAVASCRIPT = 'const meta = document.createElement(\'meta\'); meta.setAttribute(\'content\', \'width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0\'); meta.setAttribute(\'name\', \'viewport\'); document.getElementsByTagName(\'head\')[0].appendChild(meta); '
<WebView
injectedJavaScript={INJECTEDJAVASCRIPT}
scrollEnabled
ref={(webView) => {
this.webView = webView
}}
originWhitelist={['*']}
source={{ uri: url }}
onNavigationStateChange={(navState) => {
this.setState({
backButtonEnabled: navState.canGoBack,
})
}}
/>
Note
initial-scale=1, maximum-scale=1, user-scalable=0
@erikandershed
@batmanbury If you like to disable user zoom of page you need to do it in NativeScript. Like this:
webView.ios.scrollView.minimumZoomScale = 1.0;
webView.ios.scrollView.maximumZoomScale = 1.0;
webView.ios.scalesPageToFit = false;
If this worked, this issue thread wouldn't be here. It's literally in the original post here.
@tsonevn Would you mind commenting on the state of this issue?
I've been unsuccessful in getting other suggestions to work. If you have a suggestion as a workaround, I'd love to hear it in the meantime, if this won't be getting any attention. Thanks.
Yes, @tsoeven, any solution found? NativeScript admins - this is a very important feature to a native app, can you please provide a solution?
I'd like to add that, as discussed here https://github.com/NativeScript/NativeScript/issues/5683, this causes serious WebView performance degradation.
Hi all,
I researched further the case. The only solution that I found so far and works on my side is to set minimum-scale
to 0 in the metadata as an additional property. For example:
WebView.prototype.createNativeView = function () {
var jScript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'initial-scale=1.0'); meta.setAttribute('minimum-scale', '0.0'); document.getElementsByTagName('head')[0].appendChild(meta);";
var wkUScript = WKUserScript.alloc().initWithSourceInjectionTimeForMainFrameOnly(jScript, 1, true);
..................
return new WKWebView({
frame: CGRectZero,
configuration: configuration
});
};
Keep in mind that this change should be made in node_modules/tns-core-modules/ui/web-view/web-view.ios.js
file. If you delete node_modules
folder, you should make the change again.
Manually editing code inside node_modules
is not really an option (most repo's ignore node_modules
and CI install dependencies through npm i
or npm ci
.
Regarding the performance issue @douira: As far as I can see, what matters is setting width=device-width
as part of the content
attribute on the meta name=viewport
element.
If you're in control of the content rendered inside the webview you can do this:
<script>
(function () {
setTimeout(function() {
var meta = document.querySelector(‘meta[name=“viewport”]’);
if (meta) {
meta.setAttribute(‘content’, ‘width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no’);
}
}, 0);
})();
</script>
But @mxth 's fix could also solve it if accepted på {N}, since we could just set the above as part of the content of the webview;
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
same issue
To expand on what jakobe said, editing the node modules isn't really an option. If you can, this maybe another possible solution. Extend the base WebView and modify it like so.
import {WebView} from "tns-core-modules/ui/web-view";
declare let WKUserContentController: any;
declare let WKUserScript: any;
declare let WKWebViewConfiguration: any;
declare let WKWebView: any;
declare let CGRectZero: any;
export class CustomWebview extends WebView {
/**
* Custom extended class to modify the meta data in the Webview, as scaling is ignored on iOS
*/
constructor() {
super();
// function being modified
WebView.prototype.createNativeView = function () {
// adding initial scale prop
let jScript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'initial-scale=1.0'); meta.setAttribute('content', 'minimum-scale=0.0'); document.getElementsByTagName('head')[0].appendChild(meta);";
let wkUScript = WKUserScript.alloc().initWithSourceInjectionTimeForMainFrameOnly(jScript, 1, true);
let wkUController = WKUserContentController.new();
wkUController.addUserScript(wkUScript);
let configuration = WKWebViewConfiguration.new();
configuration.userContentController = wkUController;
configuration.preferences.setValueForKey(true, "allowFileAccessFromFileURLs");
return new WKWebView({
frame: CGRectZero,
configuration: configuration
});
};
}
}
To expand on what jakobe said, editing the node modules isn't really an option. If you can, this maybe another possible solution. Extend the base WebView and modify it like so.
import {WebView} from "tns-core-modules/ui/web-view"; declare let WKUserContentController: any; declare let WKUserScript: any; declare let WKWebViewConfiguration: any; declare let WKWebView: any; declare let CGRectZero: any; export class CustomWebview extends WebView { /** * Custom extended class to modify the meta data in the Webview, as scaling is ignored on iOS */ constructor() { super(); // function being modified WebView.prototype.createNativeView = function () { // adding initial scale prop let jScript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'initial-scale=1.0'); meta.setAttribute('content', 'minimum-scale=0.0'); document.getElementsByTagName('head')[0].appendChild(meta);"; let wkUScript = WKUserScript.alloc().initWithSourceInjectionTimeForMainFrameOnly(jScript, 1, true); let wkUController = WKUserContentController.new(); wkUController.addUserScript(wkUScript); let configuration = WKWebViewConfiguration.new(); configuration.userContentController = wkUController; configuration.preferences.setValueForKey(true, "allowFileAccessFromFileURLs"); return new WKWebView({ frame: CGRectZero, configuration: configuration }); }; } }
how do you apply it? I mean where do I put that in my code?
I'm using angular so do I have to like register it as element?
how do you apply it? I mean where do I put that in my code?
I'm using angular so do I have to like register it as element?
I am not using angular but I would imagine its very similar as it's just an extended class. So import it where ever you use webview. Then place it somewhere in your project. And then import the extended class rather than the normal webview.
So instead of:
import { WebView } from "tns-core-modules/ui/web-view";
Do this:
import {CustomWebview} from "~/app/library/CustomWebview";
....
let webView = new CustomWebview();
In current versions of {N}, it looks like @tsonevn 's change should actually go here:
node_modules/@nativescript/core/ui/web-view/web-view.ios.js
Hi all,
I researched further the case. The only solution that I found so far and works on my side is to setminimum-scale
to 0 in the metadata as an additional property. For example:WebView.prototype.createNativeView = function () { var jScript = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'initial-scale=1.0'); meta.setAttribute('minimum-scale', '0.0'); document.getElementsByTagName('head')[0].appendChild(meta);"; var wkUScript = WKUserScript.alloc().initWithSourceInjectionTimeForMainFrameOnly(jScript, 1, true); .................. return new WKWebView({ frame: CGRectZero, configuration: configuration }); };
Keep in mind that this change should be made in
node_modules/tns-core-modules/ui/web-view/web-view.ios.js
file. If you deletenode_modules
folder, you should make the change again.
I tried @tsonevn solution to fix the issue of _most_ web pages not opening in a modal webview. (Some do.) Here's the TestFlight build after applying change to the above module. https://testflight.apple.com/join/hNys1MSJ Build was done in SideKick. On my end, the pages still don't load.
I also tried the solution @Gummby, with no luck there either.
Most helpful comment
@tsonevn
Here's my solution https://github.com/mxth/NativeScript/commit/d7ae10566ef42f32571f2e691be6bb90f75d6521