Flutter WebView

Yubaraj poudel
Jun 12 · 4 min read

Webview is the fundamental widgets needed in mobile applications. Basically, webview is used to load the URL in view. Implementing webview in flutter is very easy if you have previous experience in native app development or not at all.

To use in the app in pubsec.yaml need to add the dependencies and inside the terminal run command flutter packages get

dependencies:
flutter:
sdk: flutter

# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
webview_flutter: ^0.3.9+1

WebView is a widget and can be added in the widget tree. A simple example of Webview

class MyWebView extends StatefulWidget {
@override
_MyWebViewState createState() => _MyWebViewState();
}

class _MyWebViewState extends State<MyWebView> {
String url = "http://yubarajpoudel.com";

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Profile"),
),
body: WebView(
initialUrl: url,
javascriptMode: JavascriptMode.unrestricted,
onPageFinished: (url) {
print("Loaded $url");
},
));
}
}

By default javascript in webview is disabled. JavascriptMode.unrestricted properties enable the JavaScript in the webview.

Let's take another example of communicating between the Javascript and widget and we can easily change the state.

The simple Html page lets name it as a samplepage.html` and keep in the assets/pages/

<html>
<head>
<title>Sample page</title>
<script>
function changeColor() {
var colors = ["black", "red", "green"];
var randonNumber = Math.floor(Math.random() * 3);
var myDiv = document.getElementById("container_box");
myDiv.style.backgroundColor = colors[randonNumber];
try { colorChanged.postMessage(colors[randonNumber]); } catch (err) {}
}
</script>
<style type="text/css">
#btn_color {
display: block;
margin: auto;
}
#container_box {
height: 500px;
width: 150px;
border: 1px solid #000 ;
margin: 0 auto;
}

</style>
</head>
<body>
<div id="container_box"></div> <br>
<button id="btn_color" onclick="changeColor()"> Change Color</button>
</body>
</html>
samplepage.html

Above file is a simple HTML file in which the div color is changed randomly when the button is clicked. Now I am showing the example how can we communicate between JavaScript and widget via JavaScriptChannel . JavaScriptChannel consists of Set of channelname on which it listens triggered by the function with the same name in JavaScript . In the below example colorChanged is the channel name which is invoked in samplepage.html changeColor function.

class _MyWebView2State extends State<MyWebView2> {
WebViewController _controller;
String _inital = "Press button to change color";

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("$_inital"),
),
body: WebView(
onWebViewCreated: (webViewController) {
_controller = webViewController;
_loadHtmlFromAssets();
},
javascriptMode: JavascriptMode.unrestricted,
javascriptChannels: Set.from([
JavascriptChannel(
name: "colorChanged",
onMessageReceived: (JavascriptMessage result) {
print("message ${result.message}");
setState(() {
_inital = "Color changed to ${result.message}";
});
}),
]),
));
}

_loadHtmlFromAssets() async {
String fileText =
await rootBundle.loadString('assets/pages/samplepage.html');
_controller.loadUrl(Uri.dataFromString(fileText,
mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
.toString());
}
}

When you run this you will get the following output.

Here when button has pressed the color of div and title in the appbar is changed

Gesture detector in the webview

By default, the gesture in other widget in the widget tree has first priority than webview . However, the gesture detection priority can be changed in webview with respect to different events. Here let's take an example of implementing the webview with vertical gesture detector in the listview. By default, the listview has the first priority while scrolling up and down. But we can change to make the webview widget to scroll when scrolled in the webview by adding gesture set.

class MyWebView3 extends StatefulWidget {
@override
_MyWebView3State createState() => _MyWebView3State();
}

class _MyWebView3State extends State<MyWebView3> {
@override
Widget build(BuildContext context) {
List urls = [
"https://flutter.dev/",
"https://google.com/",
"https://github.com/yubarajpoudel"
];
List titles = ["flutter site", "google site", "author site"];
return Scaffold(
appBar: AppBar(
title: Text("Webview 3"),
),
body: ListView.builder(
itemCount: 3,
itemBuilder: (item, index) {
return Container(
height: 200.0,
child: ListTile(
title: Text(titles[index]),
subtitle: WebView(
initialUrl: urls[index],
gestureRecognizers: Set()
..add(Factory<VerticalDragGestureRecognizer>(
() => VerticalDragGestureRecognizer())),
)));
}),
);
}
}

.. operators here reduced the initialization and return the object. In the example, webview is scrolled when scrolled on top of webview widget. Running the Snippet produces the following output.

For more information check out the flutter developer session or watch the Emily Fortuna beautiful video about flutter_webview.

If you like to contribute to help the developer community we heartily welcome to join as the contributor. Please make a PR and we will review as soon as possible. For contribution and full code, please visit following GitHub link.

https://github.com/flutterchallenge/widgetchallenge

Yubaraj poudel

Written by

Senior Software engineer | Blogger

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade