'Flutter - Disable navigation InAppWebView
I'm new to Flutter, and I want to put a web view between other widgets and I'm using the InAppWebView flutter in order to do it, but I want to prevent the user to navigate to other pages when he clicks on a button inside the web view. Do I have to write some native code for iOS and Android to prevent the navigation?
Thanks
Solution 1:[1]
something like that:
InAppWebView(
....
shouldOverrideUrlLoading: (controller, navigationAction) async {
final uri = navigationAction.request.url!;
if(whitenAvigationHosts.contains(uri.host)){
return NavigationActionPolicy.ALLOW;
}
return NavigationActionPolicy.CANCEL;
})
Solution 2:[2]
For disable navigate user to another page you can use onPageCommitVisible call back to determine the user is click on url that redirect to another one, so just call goBack inside it
InAppWebView(
onPageCommitVisible: (con,uri){
print("url ${uri.toString()}");
con.goBack();
},
),
Solution 3:[3]
Since you are using InAppWebView
package you can intercept each URL the Webview would navigate to before it is actually navigate and then make a decision of whether to navigate or not using the callback shouldOverrideUrlLoading
like the following:
shouldOverrideUrlLoading: (controller, navigationAction) async {
// You can access the URL like this
final url = navigationAction.request.url.toString();
if (condition) {
// This one means do not navigate
return NavigationActionPolicy.CANCEL;
}
// This one means navigate
return NavigationActionPolicy.ALLOW;
},
Note that to use the callback shouldOverrideUrlLoading
, you have to enable it in the initialOptions
of the webview like the following because the default is false
:
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
),
),
Solution 4:[4]
You can prevent navigation in webview through navigation delegate property like following:
WebView(
debuggingEnabled: true,
initialUrl: _currentURL,
onWebViewCreated: (controller) {
_controller = controller;
return _controller;
},
onPageFinished: (url) {
if (url.contains(ConstUtils.course)) {
updateProfile();
}
},
navigationDelegate: (navigation) => NavigationDecision.prevent,
onWebResourceError: (error) {
NavigationUtils(context).popCurrentPage();
},
onPageStarted: (url) {
},
javascriptMode: JavascriptMode.unrestricted,
),
Solution 5:[5]
Disable navigation InAppWebView
:-
we have onUpdateVisitedHistory
property in Inappwebview
widget.Using this onUpdateVisitedHistory
property we can listen url changes in the Inappwebview
widget.So disable navigation we can use webcontroller.goback()
method.
widget code:
InAppWebView(
key: webViewKey,
onWebViewCreated: (controller) {
webViewController = controller;
_loadHtmlFromAssets();
},
onUpdateVisitedHistory: (controller, url, androidIsReload) {
if (url!.host.contains("google.com")) {
webViewController?.goBack();
//You can do anything
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Screen1()),
);
//Prevent that url works
return;
} else if (url.host.contains("yahoo.com")) {
//You can do anything
webViewController?.goBack();
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Screen3()),
);
//Prevent that url works
return;
} else if (url.host.contains("duckduckgo.com")) {
//You can do anything
webViewController?.goBack();
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Screen2()),
);
}
})
Here we skipping loading the search engine and jump to other widget
nb: if we did'nt add webcontroller.goback()
.it will load site and move to the widget .if we back pressed it will show webpage.
sampleCode:
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
WebViewController? _controller;
void _incrementCounter() {
setState(() {
_counter++;
});
}
final GlobalKey webViewKey = GlobalKey();
InAppWebViewController? webViewController;
late PullToRefreshController pullToRefreshController;
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
useShouldOverrideUrlLoading: true,
mediaPlaybackRequiresUserGesture: false,
),
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
),
ios: IOSInAppWebViewOptions(
allowsInlineMediaPlayback: true,
));
@override
void initState() {
super.initState();
pullToRefreshController = PullToRefreshController(
options: PullToRefreshOptions(
color: Colors.blue,
),
onRefresh: () async {
if (Platform.isAndroid) {
webViewController?.reload();
} else if (Platform.isIOS) {
webViewController?.loadUrl(
urlRequest: URLRequest(url: await webViewController?.getUrl()));
}
},
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
webViewController?.goBack();
},
child: Icon(Icons.arrow_back),
),
appBar: AppBar(
backgroundColor: Colors.black87,
title: Text(widget.title),
),
body: Center(
child: InAppWebView(
key: webViewKey,
onWebViewCreated: (controller) {
webViewController = controller;
_loadHtmlFromAssets();
},
onUpdateVisitedHistory: (controller, url, androidIsReload) {
if (url!.host.contains("google.com")) {
webViewController?.goBack();
//You can do anything
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Screen1()),
);
//Prevent that url works
return;
} else if (url.host.contains("yahoo.com")) {
//You can do anything
webViewController?.goBack();
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Screen3()),
);
//Prevent that url works
return;
} else if (url.host.contains("duckduckgo.com")) {
//You can do anything
webViewController?.goBack();
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Screen2()),
);
}
}),
));
}
_loadHtmlFromAssets() {
var fileText =
"<!DOCTYPE html> <html> <head> <title>HTML, CSS and JavaScript demo</title> <style> .rotate { transform: rotate(1700deg) ; } .rotate2 { transform: rotate(90deg) ; } .bg { background: url(https://picsum.photos/2000/1000?image=1069) center/cover; height: 50vh; width: 50vh; } body { margin:0; overflow:hidden; } </style> </head> "
"<!-- Start your code here --> <ul> <li> <a href ='http://duckduckgo.com/' /><p> duckduckgo.com</a> </li> <li> <a href='http://www.google.com'>google.com </a> </li> <li> <a href='http://www.yahoo.com/'> yahoo.com </a> </li></ul> </html>";
// return Uri.dataFromString(fileText,
// mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
// .toString();
webViewController!.loadUrl(
urlRequest: URLRequest(
url: new Uri.dataFromString(fileText, mimeType: 'text/html')));
// _controller?.loadUrl(Uri.dataFromString(fileText,
// mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
// .toString());
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class Screen1 extends StatelessWidget {
const Screen1({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: Text("Screen 1 google.com"),
),
);
}
}
class Screen2 extends StatelessWidget {
const Screen2({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: MaterialApp(
home: Container(
child: Text("Screen 2 yahoo.com"),
),
),
);
}
}
class Screen3 extends StatelessWidget {
const Screen3({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(
child: Text("Screen 3 duck.com"),
),
);
}
}
Disable navigation in Webview
Widget:
We can use navigationDelegate
to monitor url changes in webview
.NavigationDecision.prevent
will block jump to website
WebView(
// initialUrl: 'https://flutter.dev',
onWebViewCreated: (WebViewController webViewController) {
_controller = webViewController;
_loadHtmlFromAssets();
},
navigationDelegate: (NavigationRequest request) {
if (request.url.contains("google.com")) {
//You can do anything
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Screen1()),
);
//Prevent that url works
return NavigationDecision.prevent;
} else if (request.url.contains("yahoo.com")) {
//You can do anything
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Screen1()),
);
//Prevent that url works
return NavigationDecision.prevent;
} else if (request.url.contains("duckduckgo.com")) {
//You can do anything
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const Screen3()),
);
//Prevent that url works
return NavigationDecision.prevent;
}
//Any other url works
return NavigationDecision.navigate;
},
);
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Marcelo Juan Cabrera Gutierrez |
Solution 2 | Mahmoud Abu Alheja |
Solution 3 | Moaz El-sawaf |
Solution 4 | Jay Dangar |
Solution 5 | lava |