Newby Coder header banner

Flutter Webview

Using webview in a Flutter Android/iOS application

Webview is typically a cross-platform library used to render web based User Interfaces in mobile or desktop applications

flutter_webview_plugin package provides FlutterWebviewPlugin and WebviewScaffold to render a webview and interact with it


Creating new Flutter App

Check Flutter installation to setup Flutter

Use flutter create command to create a Flutter project (here webview_app :

flutter create webview_app

Dependency

Implementation

Importing Package

import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';

Create WebviewScaffold

Create WebviewScaffold widget which is like a Scaffold and contains properties for webview

A selectedUrl String indicates the url being browsed

initialChild can be used to show a widget while a page is loaded, whereas setting hidden to true shows a circular progress indicator

  @override
  Widget build(BuildContext context) {
    return WebviewScaffold(
      url: selectedUrl,
      mediaPlaybackRequiresUserGesture: false,
      appBar: AppBar(
        automaticallyImplyLeading: false,
        title:Text("Webview Example App"),
        bottom: AppBar(
          automaticallyImplyLeading: false,
      ),
      withZoom: true,
      withLocalStorage: true,
      hidden: false,
      initialChild: Container(
        color: Colors.redAccent,
        child: const Center(
          child: Text('Waiting.....'),
        ),
      ),
    );
}

FlutterWebviewPlugin instance

Declare an instance of FlutterWebviewPlugin which is a singleton instance linked to an unique webview

final flutterWebViewPlugin = FlutterWebviewPlugin(); 

Use it to initiate functions like reload, goForward, goBack() and to implement listeners like onUrlChanged, onHttpError etc

flutterWebViewPlugin.reload();
flutterWebViewPlugin.goForward();
flutterWebViewPlugin.goBack();
flutterWebViewPlugin.getCookies();

flutterWebViewPlugin.onUrlChanged.listen((String url) {
  if (mounted) {
    setState(() {
      _urlCtrl.text = selectedUrl;
      selectedUrl = url;
      _history.add('onUrlChanged: $url');
    });
  }
});

App Code

viewpager_app/lib/main.dart
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';


// ignore: prefer_collection_literals
final Set<JavascriptChannel> jsChannels = [
  JavascriptChannel(
      name: 'Print',
      onMessageReceived: (JavascriptMessage message) {
        print(message.message);
      }),
].toSet();

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(WebviewApp());
}

class WebviewApp extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter WebView Example App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      routes: {
        '/': (_) => const WebviewScreen(title: 'Flutter WebView Example App'),
      },
    );
  }
}

class WebviewScreen extends StatefulWidget {
  const WebviewScreen({Key key, this.title}) : super(key: key);
  final String title;

  @override
  _WebviewScreenState createState() => _WebviewScreenState();
}

class _WebviewScreenState extends State<WebviewScreen> {
  final flutterWebViewPlugin = FlutterWebviewPlugin();
   String selectedUrl = 'https://flutter.io';
  // On destroy stream
  StreamSubscription _onDestroy;

  // On urlChanged stream
  StreamSubscription<String> _onUrlChanged;

  StreamSubscription<WebViewStateChanged> _onStateChanged;
  StreamSubscription<WebViewHttpError> _onHttpError;
  StreamSubscription<double> _onProgressChanged;
  StreamSubscription<double> _onScrollYChanged;
  StreamSubscription<double> _onScrollXChanged;

  final _urlCtrl = TextEditingController(text: 'https://flutter.io');
  final _scaffoldKey = GlobalKey<ScaffoldState>();
  final _history = [];

  @override
  void initState() {
    super.initState();
    flutterWebViewPlugin.close();
    _urlCtrl.addListener(() {
      selectedUrl = _urlCtrl.text;
    });

    // Add a listener to on destroy WebView, so you can make came actions.
    _onDestroy = flutterWebViewPlugin.onDestroy.listen((_) {
      if (mounted) {
        // Actions like show a info toast.
        _scaffoldKey.currentState.showSnackBar(
            const SnackBar(content: const Text('Webview Destroyed')));
      }
    });

    // Add a listener to on url changed
    _onUrlChanged = flutterWebViewPlugin.onUrlChanged.listen((String url) {
      if (mounted) {
        setState(() {
          _urlCtrl.text = selectedUrl;
          selectedUrl = url;
          _history.add('onUrlChanged: $url');
        });
      }
    });

    _onProgressChanged =
        flutterWebViewPlugin.onProgressChanged.listen((double progress) {
      if (mounted) {
        setState(() {
          _history.add('onProgressChanged: $progress');
        });
      }
    });

    _onScrollYChanged =
        flutterWebViewPlugin.onScrollYChanged.listen((double y) {
      if (mounted) {
        setState(() {
          // _history.add('Scroll in Y Direction: $y');
        });
      }
    });

    _onScrollXChanged =
        flutterWebViewPlugin.onScrollXChanged.listen((double x) {
      if (mounted) {
        setState(() {
          // _history.add('Scroll in X Direction: $x');
        });
      }
    });

    _onStateChanged =
        flutterWebViewPlugin.onStateChanged.listen((WebViewStateChanged state) {
      if (mounted) {
        setState(() {
          _history.add('onStateChanged: ${state.type} ${state.url}');
        });
      }
    });

    _onHttpError =
        flutterWebViewPlugin.onHttpError.listen((WebViewHttpError error) {
      if (mounted) {
        setState(() {
          _history.add('onHttpError: ${error.code} ${error.url}');
        });
      }
    });
  }

  @override
  void dispose() {
    _onDestroy.cancel();
    _onUrlChanged.cancel();
    _onStateChanged.cancel();
    _onHttpError.cancel();
    _onProgressChanged.cancel();
    _onScrollXChanged.cancel();
    _onScrollYChanged.cancel();

    flutterWebViewPlugin.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return WebviewScaffold(
      url: selectedUrl,
      javascriptChannels: jsChannels,
      mediaPlaybackRequiresUserGesture: false,
      appBar: AppBar(
        automaticallyImplyLeading: false,
        title:Text("Webview Example App"),
        bottom: AppBar(
          automaticallyImplyLeading: false,
          title: Row(
            children: <Widget>[
              Expanded(
                flex: 1,
                child: IconButton(
                  icon: const Icon(Icons.arrow_back_ios),
                  onPressed: () {
                    flutterWebViewPlugin.goBack();
                  },
                ),
              ),
              Expanded(
                flex: 1,
                child: IconButton(
                  icon: const Icon(Icons.arrow_forward_ios),
                  onPressed: () {
                    flutterWebViewPlugin.goForward();
                  },
                ),
              ),
              Expanded(
                flex: 8,
                child:Container(
                  padding: EdgeInsets.only(top:5, bottom:5),
                  color: Colors.white,
                  child: TextField(controller: _urlCtrl),
                ),
              ),
              Expanded(
                flex: 1,
                child: IconButton(
                  icon: const Icon(Icons.autorenew),
                  onPressed: () {
                    flutterWebViewPlugin.reload();
                  },
                ),
              ),
            ],
          ),
        ),
      ),
      withZoom: true,
      withLocalStorage: true,
      hidden: false,
      initialChild: Container(
        color: Colors.redAccent,
        child: const Center(
          child: Text('Waiting.....'),
        ),
      ),
      bottomNavigationBar: Container(
        height:100,
        child:SingleChildScrollView(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                child: Text('${selectedUrl}', style: TextStyle(color: Colors.black, fontWeight:FontWeight.normal, fontSize:15,)),
              ),
              RaisedButton(
                onPressed: () {
                  flutterWebViewPlugin.getCookies().then((m) {
                    setState(() {
                      _history.add('cookies: $m');
                    });
                  });
                },
                child: const Text('Cookies'),
              ),
              Text(_history.join('\n'))
            ],
          ),
        ),
      ),
    );
  }
}

Run instructions

Ensure a supported device is connected or emulator/simulator is started

Go to project directory

Use flutter run command to run

flutter run

It builds and runs app on an available android/ios device


Screenshot/image

Android

cl-flutter-webview

iOS

cm_flutter_webview_as1cm_flutter_webview_as2cm_flutter_webview_as3