DEV Community

Cover image for Starting with Flutter: How to embed a webview
TheOtherDev/s
TheOtherDev/s

Posted on

Starting with Flutter: How to embed a webview

In this tutorial you will learn how to use WebViews in your Flutter application. With WebViews you can embed web contents inside your app. We will use the webview_flutter package that uses native WebViews (WKWebView on iOS and WebView on Android).

The first thing that you have to do is to add the package to your pubspec.yaml file:

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^1.0.2
  webview_flutter: ^2.1.2
Enter fullscreen mode Exit fullscreen mode

After this run flutter pub get, or use the Pub get button.

Now create a new file webview_scaffold.dart, and create a new StatefulWidget called WebViewScaffold.
Adding a WebView is very simple, we will need to use the WebView Widget as the body of the Scaffold. In the following example the WebView will open https://google.com.

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class WebViewScaffold extends StatefulWidget {
  const WebViewScaffold({Key? key}) : super(key: key);

  @override
  State<WebViewScaffold> createState() => _WebViewScaffoldState();
}

class _WebViewScaffoldState extends State<WebViewScaffold> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('WebView'),
      ),
      body: WebView(
        initialUrl: 'https://google.com',
        javascriptMode: JavascriptMode.unrestricted,
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Navigation

We can manage the navigation in our WebView, to do so we will use the WebViewController object. This is created by the WebView widget and passed in a callback that's called once the WebView is created.
Let's add the WebViewController to our state and save it for later, when the callback is invoked.

class _WebViewScaffoldState extends State<WebViewScaffold> {
  WebViewController? _controller;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('WebView'),
      ),
      body: WebView(
        initialUrl: 'https://google.com',
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (controller) {
          setState(() {
            _controller = controller;
          });
        },
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Now we just need to use the controller to make thee WebView go back, go forward or reload. The WebViewController has functions to go back, forward, reload and to check if the WebView can go back or go forward.
We will put those buttons in a BottomAppBar as the bottomNavigationBar of our Scaffold.

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class WebViewScaffold extends StatefulWidget {
  const WebViewScaffold({Key? key}) : super(key: key);

  @override
  State<WebViewScaffold> createState() => _WebViewScaffoldState();
}

class _WebViewScaffoldState extends State<WebViewScaffold> {
  WebViewController? _controller;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('WebView'),
      ),
      body: WebView(
        initialUrl: 'https://google.com',
        javascriptMode: JavascriptMode.unrestricted,
        onWebViewCreated: (controller) {
          setState(() {
            _controller = controller;
          });
        },
        onPageFinished: (_) {
          setState(() {});
        },
      ),
      bottomNavigationBar: _controller != null
          ? _WebViewNavigationBar(controller: _controller!)
          : null,
    );
  }
}

class _WebViewNavigationBar extends StatelessWidget {
  final WebViewController controller;

  const _WebViewNavigationBar({
    Key? key,
    required this.controller,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return BottomAppBar(
      child: SizedBox(
        height: 60,
        child: IconTheme(
          data: IconThemeData(color: Colors.blue),
          child: Row(
            children: [
              FutureBuilder<bool>(
                future: controller.canGoBack(),
                builder: (context, snapshot) => IconButton(
                  icon: Icon(Icons.arrow_back),
                  onPressed:
                      snapshot.data == true ? () => controller.goBack() : null,
                ),
              ),
              FutureBuilder<bool>(
                future: controller.canGoForward(),
                builder: (context, snapshot) => IconButton(
                  icon: Icon(Icons.arrow_forward),
                  onPressed: snapshot.data == true
                      ? () => controller.goForward()
                      : null,
                ),
              ),
              Expanded(child: Container()),
              IconButton(
                icon: Icon(Icons.refresh),
                onPressed: () => controller.reload(),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
Enter fullscreen mode Exit fullscreen mode

Discussion (0)