Ios webview controller button next page on navigation top năm 2024

With the WebView Flutter plugin you can add a WebView widget to your Android or iOS Flutter app. On iOS the WebView widget is backed by a WKWebView, while on Android the WebView widget is backed by a WebView. The plugin can render Flutter widgets over the web view. So for example it's possible to render a drop down menu over the web view.

What you'll build

In this codelab, you'll build a mobile app step by step featuring a WebView using the Flutter SDK. Your app will:

  • Display web content in a

    import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; void main() { runApp(

    const MaterialApp(  
      theme: ThemeData(useMaterial3: true),  
      home: WebViewApp(),  
    ),  
    
    ); } class WebViewApp extends StatefulWidget { const WebViewApp({super.key}); @override State<WebViewApp> createState() => _WebViewAppState(); } class _WebViewAppState extends State<WebViewApp> { late final WebViewController controller; @override void initState() {
    super.initState();  
    controller = WebViewController()  
      ..loadRequest(  
        Uri.parse('https://flutter.dev'),  
      );  
    
    } @override Widget build(BuildContext context) {
    return Scaffold(  
      appBar: AppBar(  
        title: const Text('Flutter WebView'),  
      ),  
      body: WebViewWidget(  
        controller: controller,  
      ),  
    );  
    
    } }

    6
  • Display Flutter widgets stacked over the

    import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; void main() { runApp(

    const MaterialApp(  
      theme: ThemeData(useMaterial3: true),  
      home: WebViewApp(),  
    ),  
    
    ); } class WebViewApp extends StatefulWidget { const WebViewApp({super.key}); @override State<WebViewApp> createState() => _WebViewAppState(); } class _WebViewAppState extends State<WebViewApp> { late final WebViewController controller; @override void initState() {
    super.initState();  
    controller = WebViewController()  
      ..loadRequest(  
        Uri.parse('https://flutter.dev'),  
      );  
    
    } @override Widget build(BuildContext context) {
    return Scaffold(  
      appBar: AppBar(  
        title: const Text('Flutter WebView'),  
      ),  
      body: WebViewWidget(  
        controller: controller,  
      ),  
    );  
    
    } }

    6
  • React to page load progress events
  • Control the

    import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; void main() { runApp(

    const MaterialApp(  
      theme: ThemeData(useMaterial3: true),  
      home: WebViewApp(),  
    ),  
    
    ); } class WebViewApp extends StatefulWidget { const WebViewApp({super.key}); @override State<WebViewApp> createState() => _WebViewAppState(); } class _WebViewAppState extends State<WebViewApp> { late final WebViewController controller; @override void initState() {
    super.initState();  
    controller = WebViewController()  
      ..loadRequest(  
        Uri.parse('https://flutter.dev'),  
      );  
    
    } @override Widget build(BuildContext context) {
    return Scaffold(  
      appBar: AppBar(  
        title: const Text('Flutter WebView'),  
      ),  
      body: WebViewWidget(  
        controller: controller,  
      ),  
    );  
    
    } }

    6 through the

    import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; void main() { runApp(

    const MaterialApp(  
      theme: ThemeData(useMaterial3: true),  
      home: WebViewApp(),  
    ),  
    
    ); } class WebViewApp extends StatefulWidget { const WebViewApp({super.key}); @override State<WebViewApp> createState() => _WebViewAppState(); } class _WebViewAppState extends State<WebViewApp> { late final WebViewController controller; @override void initState() {
    super.initState();  
    controller = WebViewController()  
      ..loadRequest(  
        Uri.parse('https://flutter.dev'),  
      );  
    
    } @override Widget build(BuildContext context) {
    return Scaffold(  
      appBar: AppBar(  
        title: const Text('Flutter WebView'),  
      ),  
      body: WebViewWidget(  
        controller: controller,  
      ),  
    );  
    
    } }

    9
  • Block websites using the $ flutter run 0
  • Evaluate JavaScript expressions
  • Handle callbacks from JavaScript with $ flutter run 1
  • Set, remove, add or show cookies
  • Load and display HTML from assets, files or Strings containing HTML

Ios webview controller button next page on navigation top năm 2024

Ios webview controller button next page on navigation top năm 2024

What you'll learn

In this codelab you'll learn how to use the

$ flutter run

2 plugin in a variety of ways, including:

  • How to configure the $ flutter run 2 plugin
  • How to listen for page load progress events
  • How to control page navigation
  • How to command the

    import 'package:flutter/material.dart'; import 'package:webview_flutter/webview_flutter.dart'; void main() { runApp(

    const MaterialApp(  
      theme: ThemeData(useMaterial3: true),  
      home: WebViewApp(),  
    ),  
    
    ); } class WebViewApp extends StatefulWidget { const WebViewApp({super.key}); @override State<WebViewApp> createState() => _WebViewAppState(); } class _WebViewAppState extends State<WebViewApp> { late final WebViewController controller; @override void initState() {
    super.initState();  
    controller = WebViewController()  
      ..loadRequest(  
        Uri.parse('https://flutter.dev'),  
      );  
    
    } @override Widget build(BuildContext context) {
    return Scaffold(  
      appBar: AppBar(  
        title: const Text('Flutter WebView'),  
      ),  
      body: WebViewWidget(  
        controller: controller,  
      ),  
    );  
    
    } }

    6 to go backwards and forwards through its history
  • How to evaluate JavaScript, including using returned results
  • How to register callbacks to call Dart code from JavaScript
  • How to manage cookies
  • How to load and display HTML pages from assets or files or String containing HTML

What you'll need

  • Android Studio 4.1 or later (for Android development)
  • Xcode 12 or later (for iOS development)
  • Flutter SDK
  • A code editor, such as Android Studio, Visual Studio Code, or Emacs.

2. Set up your Flutter development environment

You need two pieces of software to complete this lab—the Flutter SDK and an editor.

You can run the codelab using any of these devices:

  • A physical or device connected to your computer and set to Developer mode.
  • The (requires installing Xcode tools).
  • The (requires setup in Android Studio).

3. Getting started

Getting started with Flutter

There are a variety of ways of creating a new Flutter project, with both Android Studio and Visual Studio Code providing tooling for this task. Either follow the linked procedures to create a project, or execute the following commands in a handy command line terminal.

$ flutter create --platforms=android,ios webview_in_flutter Creating project webview_in_flutter... Running "flutter pub get" in webview_in_flutter... 1,728ms Wrote 73 files. All done! In order to run your application, type: $ cd webview_in_flutter $ flutter run Your application code is in webview_in_flutter/lib/main.dart.

Adding WebView Flutter plugin as a dependency

Adding additional capability to a Flutter app is easy using Pub packages. In this codelab you will add the

$ flutter run

2 plugin to your project. Run the following commands in the terminal.

$ cd webview_in_flutter $ flutter pub add webview_flutter

If you inspect your pubspec.yaml, you will now see it has a line in the dependencies section for the

$ flutter run

2 plugin.

Configure Android minSDK

To use the

$ flutter run

2 plugin on Android you need to set the

$ flutter run

8 to

$ flutter run

9. Modify your

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

0 file as follows:

android/app/build.gradle

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

4. Adding WebView widget to the Flutter App

In this step you will add a

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 to your application. WebViews are hosted native views, and you as an app developer have a choice on how to host these native views in your app. On Android you have a choice between Virtual Displays, currently the default for Android, and Hybrid composition. However, iOS always uses Hybrid composition.

For an in depth discussion of the differences between Virtual Displays and Hybrid composition, please read through the documentation on Hosting native Android and iOS views in your Flutter app with Platform Views.

Putting a Webview on the screen

Replace the content of

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

2 with the following:

lib/main.dart

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

Running this on iOS or Android will show a WebView as a full bleed browser window on your device, which means that the browser is shown on your device in fullscreen without any form of border or margin. As you scroll, you will notice parts of the page that might look a bit odd. This is because JavaScript is currently disabled and rendering flutter.dev properly requires JavaScript.

Running the app

Run the Flutter app in either iOS or Android to see a Webview, which displays the flutter.dev website. Alternatively run the app in either an Android emulator or an iOS simulator. Feel free to replace the initial WebView URL with for example your own website.

$ flutter run

Assuming that you have the appropriate simulator or emulator running, or a physical device attached, after compiling and deploying the app to your device, you should see something like the following:

Ios webview controller button next page on navigation top năm 2024

Ios webview controller button next page on navigation top năm 2024

5. Listening for page load events

The

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 widget provides several page load progress events, which your app can listen to. During the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 page load cycle there are three different page load events that are fired:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

5,

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

6, and

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

7. In this step you will implement a page load indicator. As a bonus, this will show that you can render Flutter content over the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 content area.

Adding page load events to your app

Create a new source file at

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

9 and fill it with the following content:

lib/src/web_view_stack.dart

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

This code has wrapped the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 widget in a

import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: const WebViewStack(),
    );
  }
}

1, conditionally overlaying the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 with a

import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: const WebViewStack(),
    );
  }
}

3 when the page load percentage is less than 100%. As this involves program state that changes over time, you have stored this state in a

import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: const WebViewStack(),
    );
  }
}

4 class associated with a

import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: const WebViewStack(),
    );
  }
}

5.

To make use of this new

import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: const WebViewStack(),
    );
  }
}

6 widget, modify your lib/main.dart as follows:

lib/main.dart

import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: const WebViewStack(),
    );
  }
}

When you run the app, depending on your network conditions, and whether the browser has cached the page you are navigating to, you will see a page loading indicator overlaid on top of the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 content area.

6. Working with the WebViewController

The

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 widget enables programmatic control with a

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9. This controller is made available after the construction of the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 widget through a callback. The asynchronous nature of the availability of this controller makes it a prime candidate for Dart's asynchronous

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({required this.controller, super.key}); // MODIFY
  final WebViewController controller;                        // ADD
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  // REMOVE the controller that was here
  @override
  void initState() {
    super.initState();
    // Modify from here...
    widget.controller.setNavigationDelegate(
      NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ),
    );
    // ...to here.
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: widget.controller,                     // MODIFY
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

1 class.

Update

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

9 as follows:

lib/src/web_view_stack.dart

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({required this.controller, super.key}); // MODIFY
  final WebViewController controller;                        // ADD
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  // REMOVE the controller that was here
  @override
  void initState() {
    super.initState();
    // Modify from here...
    widget.controller.setNavigationDelegate(
      NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ),
    );
    // ...to here.
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: widget.controller,                     // MODIFY
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

The

import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: const WebViewStack(),
    );
  }
}

6 widget now uses a controller created in the surrounding widget. This will enable the controller for the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({required this.controller, super.key}); // MODIFY
  final WebViewController controller;                        // ADD
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  // REMOVE the controller that was here
  @override
  void initState() {
    super.initState();
    // Modify from here...
    widget.controller.setNavigationDelegate(
      NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ),
    );
    // ...to here.
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: widget.controller,                     // MODIFY
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

4 to be shared with other parts of the app easily.

Crafting Navigation Controls

Having a working

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 is one thing, but being able to navigate backwards and forwards through the page history, and reload the page, would be a useful set of additions. Thankfully, with a

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9 you can add this functionality to your app.

Create a new source file at

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({required this.controller, super.key}); // MODIFY
  final WebViewController controller;                        // ADD
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  // REMOVE the controller that was here
  @override
  void initState() {
    super.initState();
    // Modify from here...
    widget.controller.setNavigationDelegate(
      NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ),
    );
    // ...to here.
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: widget.controller,                     // MODIFY
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

7 and fill it with the following:

lib/src/navigation_controls.dart

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class NavigationControls extends StatelessWidget {
  const NavigationControls({required this.controller, super.key});
  final WebViewController controller;
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        IconButton(
          icon: const Icon(Icons.arrow_back_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoBack()) {
              await controller.goBack();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No back history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.arrow_forward_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoForward()) {
              await controller.goForward();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No forward history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.replay),
          onPressed: () {
            controller.reload();
          },
        ),
      ],
    );
  }
}

This widget uses the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9 shared with it at construction time to enable the user control the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 through a series of

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class NavigationControls extends StatelessWidget {
  const NavigationControls({required this.controller, super.key});
  final WebViewController controller;
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        IconButton(
          icon: const Icon(Icons.arrow_back_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoBack()) {
              await controller.goBack();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No back history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.arrow_forward_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoForward()) {
              await controller.goForward();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No forward history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.replay),
          onPressed: () {
            controller.reload();
          },
        ),
      ],
    );
  }
}

0s.

Adding navigation controls to the AppBar

With the updated

import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: const WebViewStack(),
    );
  }
}

6, and the newly crafted

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class NavigationControls extends StatelessWidget {
  const NavigationControls({required this.controller, super.key});
  final WebViewController controller;
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        IconButton(
          icon: const Icon(Icons.arrow_back_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoBack()) {
              await controller.goBack();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No back history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.arrow_forward_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoForward()) {
              await controller.goForward();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No forward history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.replay),
          onPressed: () {
            controller.reload();
          },
        ),
      ],
    );
  }
}

2 in hand, it is now time for you to put it all together in an updated

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class NavigationControls extends StatelessWidget {
  const NavigationControls({required this.controller, super.key});
  final WebViewController controller;
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        IconButton(
          icon: const Icon(Icons.arrow_back_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoBack()) {
              await controller.goBack();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No back history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.arrow_forward_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoForward()) {
              await controller.goForward();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No forward history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.replay),
          onPressed: () {
            controller.reload();
          },
        ),
      ],
    );
  }
}

3. This is where we construct the shared

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9. With

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class NavigationControls extends StatelessWidget {
  const NavigationControls({required this.controller, super.key});
  final WebViewController controller;
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        IconButton(
          icon: const Icon(Icons.arrow_back_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoBack()) {
              await controller.goBack();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No back history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.arrow_forward_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoForward()) {
              await controller.goForward();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No forward history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.replay),
          onPressed: () {
            controller.reload();
          },
        ),
      ],
    );
  }
}

3 near the top of the Widget tree in this app, it makes sense to create it at this level.

Update

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

2 file as follows:

lib/main.dart

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';  // ADD
import 'src/navigation_controls.dart';                  // ADD
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  // Add from here...
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  // ...to here.
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
        // Add from here...
        actions: [
          NavigationControls(controller: controller),
        ],
        // ...to here.
      ),
      body: WebViewStack(controller: controller),       // MODIFY
    );
  }
}

Running the app should reveal a web page with controls:

Ios webview controller button next page on navigation top năm 2024

Ios webview controller button next page on navigation top năm 2024

7. Keeping track of navigation with the NavigationDelegate

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 provides your app with a

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class NavigationControls extends StatelessWidget {
  const NavigationControls({required this.controller, super.key});
  final WebViewController controller;
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        IconButton(
          icon: const Icon(Icons.arrow_back_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoBack()) {
              await controller.goBack();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No back history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.arrow_forward_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoForward()) {
              await controller.goForward();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No forward history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.replay),
          onPressed: () {
            controller.reload();
          },
        ),
      ],
    );
  }
}

8 which enables your app to track and control the page navigation of the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 widget. When a navigation is initiated by the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';  // ADD
import 'src/navigation_controls.dart';                  // ADD
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  // Add from here...
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  // ...to here.
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
        // Add from here...
        actions: [
          NavigationControls(controller: controller),
        ],
        // ...to here.
      ),
      body: WebViewStack(controller: controller),       // MODIFY
    );
  }
}

0 for example when a user clicks on a link, the

$ flutter run

0 is called. The

$ flutter run

0 callback can be used to control whether the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 proceeds with the navigation.

Register a custom NavigationDelegate

In this step, you will register a

$ flutter run

0 callback to block navigation to YouTube.com. Note, this simplistic implementation also blocks inline YouTube content, which appears in various Flutter API documentation pages.

Update the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

9 as follows:

lib/src/web_view_stack.dart

$ cd webview_in_flutter $ flutter pub add webview_flutter

0

In the next step, you will add a menu item to enable testing your

$ flutter run

0 by using the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9 class. It is left as an exercise to the reader to augment the logic of the callback to only block full page navigation to YouTube.com, and still allow the inline YouTube content in the API documentation.

8. Adding a menu button to the AppBar

Over the next few steps, you will craft a menu button in the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';  // ADD
import 'src/navigation_controls.dart';                  // ADD
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  // Add from here...
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  // ...to here.
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
        // Add from here...
        actions: [
          NavigationControls(controller: controller),
        ],
        // ...to here.
      ),
      body: WebViewStack(controller: controller),       // MODIFY
    );
  }
}

8 widget that is used to evaluate JavaScript, invoke JavaScript channels, and manage cookies. All in all, a useful menu indeed.

Create a new source file at

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';  // ADD
import 'src/navigation_controls.dart';                  // ADD
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  // Add from here...
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  // ...to here.
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
        // Add from here...
        actions: [
          NavigationControls(controller: controller),
        ],
        // ...to here.
      ),
      body: WebViewStack(controller: controller),       // MODIFY
    );
  }
}

9 and fill it with the following:

$ cd webview_in_flutter $ flutter pub add webview_flutter

1

When the user selects the Navigate to YouTube menu option, the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9's

$ cd webview_in_flutter $ flutter pub add webview_flutter

01 method is executed. This navigation will be blocked by the

$ cd webview_in_flutter $ flutter pub add webview_flutter

02 callback you created in the previous step.

To add the menu to the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class NavigationControls extends StatelessWidget {
  const NavigationControls({required this.controller, super.key});
  final WebViewController controller;
  @override
  Widget build(BuildContext context) {
    return Row(
      children: <Widget>[
        IconButton(
          icon: const Icon(Icons.arrow_back_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoBack()) {
              await controller.goBack();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No back history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.arrow_forward_ios),
          onPressed: () async {
            final messenger = ScaffoldMessenger.of(context);
            if (await controller.canGoForward()) {
              await controller.goForward();
            } else {
              messenger.showSnackBar(
                const SnackBar(content: Text('No forward history item')),
              );
              return;
            }
          },
        ),
        IconButton(
          icon: const Icon(Icons.replay),
          onPressed: () {
            controller.reload();
          },
        ),
      ],
    );
  }
}

3's screen, modify

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({super.key});
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..setNavigationDelegate(NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ))
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: controller,
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

2 as follows:

lib/main.dart

$ cd webview_in_flutter $ flutter pub add webview_flutter

2

Run your app and tap on the Navigate to YouTube menu item. You should be greeted with a SnackBar informing you that the navigation controller blocked navigating to YouTube.

Ios webview controller button next page on navigation top năm 2024

Ios webview controller button next page on navigation top năm 2024

9. Evaluating JavaScript

The

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9 can evaluate JavaScript expressions in the context of the current page. There are two different ways to evaluate JavaScript: for JavaScript code that doesn't return a value, use

$ cd webview_in_flutter $ flutter pub add webview_flutter

06, and for JavaScript code that does return a value, use

$ cd webview_in_flutter $ flutter pub add webview_flutter

07.

To enable JavaScript, you need to configure the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9 with the

$ cd webview_in_flutter $ flutter pub add webview_flutter

09 property set to

$ cd webview_in_flutter $ flutter pub add webview_flutter

10. By default,

$ cd webview_in_flutter $ flutter pub add webview_flutter

11 is set to

$ cd webview_in_flutter $ flutter pub add webview_flutter

12.

Update the

$ cd webview_in_flutter $ flutter pub add webview_flutter

13 class by adding the

$ cd webview_in_flutter $ flutter pub add webview_flutter

11 setting as follows:

lib/src/web_view_stack.dart

$ cd webview_in_flutter $ flutter pub add webview_flutter

3

Now that the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({required this.controller, super.key}); // MODIFY
  final WebViewController controller;                        // ADD
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  // REMOVE the controller that was here
  @override
  void initState() {
    super.initState();
    // Modify from here...
    widget.controller.setNavigationDelegate(
      NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ),
    );
    // ...to here.
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: widget.controller,                     // MODIFY
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

4 can execute JavaScript, you can add an option to the menu to use the

$ cd webview_in_flutter $ flutter pub add webview_flutter

07 method.

Using either your Editor or some keyboard work, convert the Menu class to a StatefulWidget. Modify

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';  // ADD
import 'src/navigation_controls.dart';                  // ADD
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  // Add from here...
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  // ...to here.
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
        // Add from here...
        actions: [
          NavigationControls(controller: controller),
        ],
        // ...to here.
      ),
      body: WebViewStack(controller: controller),       // MODIFY
    );
  }
}

9 to match the following:

$ cd webview_in_flutter $ flutter pub add webview_flutter

4

When you tap on the ‘Show user-agent' menu option, the result of executing the JavaScript expression

$ cd webview_in_flutter $ flutter pub add webview_flutter

18 is shown in a

$ cd webview_in_flutter $ flutter pub add webview_flutter

19. When running the app, you might notice that the Flutter.dev page looks different. This is the result of running with JavaScript enabled.

Ios webview controller button next page on navigation top năm 2024

Ios webview controller button next page on navigation top năm 2024

10. Working with JavaScript Channels

Javascript Channels enable your app to register callback handlers in the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({required this.controller, super.key}); // MODIFY
  final WebViewController controller;                        // ADD
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  // REMOVE the controller that was here
  @override
  void initState() {
    super.initState();
    // Modify from here...
    widget.controller.setNavigationDelegate(
      NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ),
    );
    // ...to here.
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: widget.controller,                     // MODIFY
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

4's JavaScript context that can be invoked to convey values back to the App's Dart code. In this step you will register a

$ cd webview_in_flutter $ flutter pub add webview_flutter

21 channel that will be called with the result of a

$ cd webview_in_flutter $ flutter pub add webview_flutter

22.

Update the

import 'package:flutter/material.dart';
import 'src/web_view_stack.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: const WebViewStack(),
    );
  }
}

6 class as follows:

lib/src/web_view_stack.dart

$ cd webview_in_flutter $ flutter pub add webview_flutter

5

For each JavaScript Channel in the

$ cd webview_in_flutter $ flutter pub add webview_flutter

24, a channel object is made available in the JavaScript context as a window property named with the same name as the JavaScript Channel

$ cd webview_in_flutter $ flutter pub add webview_flutter

25. Using this from the JavaScript context involves calling

$ cd webview_in_flutter $ flutter pub add webview_flutter

26 on the JavaScript Channel to send a message that is passed to the named

$ cd webview_in_flutter $ flutter pub add webview_flutter

27's

$ cd webview_in_flutter $ flutter pub add webview_flutter

28 callback handler.

To make use of the Javascript Channel added above, add another menu item that executes an

$ cd webview_in_flutter $ flutter pub add webview_flutter

22 in the JavaScript context and passes back the results using the

$ cd webview_in_flutter $ flutter pub add webview_flutter

21 JavaScript Channel.

Now that

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewStack extends StatefulWidget {
  const WebViewStack({required this.controller, super.key}); // MODIFY
  final WebViewController controller;                        // ADD
  @override
  State<WebViewStack> createState() => _WebViewStackState();
}
class _WebViewStackState extends State<WebViewStack> {
  var loadingPercentage = 0;
  // REMOVE the controller that was here
  @override
  void initState() {
    super.initState();
    // Modify from here...
    widget.controller.setNavigationDelegate(
      NavigationDelegate(
        onPageStarted: (url) {
          setState(() {
            loadingPercentage = 0;
          });
        },
        onProgress: (progress) {
          setState(() {
            loadingPercentage = progress;
          });
        },
        onPageFinished: (url) {
          setState(() {
            loadingPercentage = 100;
          });
        },
      ),
    );
    // ...to here.
  }
  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebViewWidget(
          controller: widget.controller,                     // MODIFY
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}

4 knows about our JavaScript Channels

$ cd webview_in_flutter $ flutter pub add webview_flutter

32you will add an example to expand the app further. To do this, add an extra

$ cd webview_in_flutter $ flutter pub add webview_flutter

33 to the

$ cd webview_in_flutter $ flutter pub add webview_flutter

34 class and add the extra functionality.

Update

$ cd webview_in_flutter $ flutter pub add webview_flutter

35 with the extra menu option, by adding the

$ cd webview_in_flutter $ flutter pub add webview_flutter

36 enumeration value, and add an implementation to the

$ cd webview_in_flutter $ flutter pub add webview_flutter

34 class as follows:

$ cd webview_in_flutter $ flutter pub add webview_flutter

6

This JavaScript is executed when the user chooses the JavaScript Channel Example menu option.

$ cd webview_in_flutter $ flutter pub add webview_flutter

7

This code sends a

$ cd webview_in_flutter $ flutter pub add webview_flutter

38 request to a Public IP Address API, returning the device's IP address. This result is shown in a

$ cd webview_in_flutter $ flutter pub add webview_flutter

21 by invoking

$ cd webview_in_flutter $ flutter pub add webview_flutter

26 on the

$ cd webview_in_flutter $ flutter pub add webview_flutter

21

$ cd webview_in_flutter $ flutter pub add webview_flutter

27.

11. Managing Cookies

Your app can manage cookies in the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 by using the

$ cd webview_in_flutter $ flutter pub add webview_flutter

44 class. In this step, you are going to show a list of cookies, clear the list of cookies, delete cookies, and set new cookies. Add entries to the

$ cd webview_in_flutter $ flutter pub add webview_flutter

35 for each of the cookie use cases as follows:

$ cd webview_in_flutter $ flutter pub add webview_flutter

8

The rest of the changes in this step are focused on the

$ cd webview_in_flutter $ flutter pub add webview_flutter

34 class, including the conversion of the

$ cd webview_in_flutter $ flutter pub add webview_flutter

34 class from stateless to stateful. This change is important because the

$ cd webview_in_flutter $ flutter pub add webview_flutter

34 needs to own the

$ cd webview_in_flutter $ flutter pub add webview_flutter

44, and mutable state in stateless widgets is a bad combination.

Add the CookieManager to the resulting State class as follows:

$ cd webview_in_flutter $ flutter pub add webview_flutter

9

The

$ cd webview_in_flutter $ flutter pub add webview_flutter

50 class will contain the code previously added in the

$ cd webview_in_flutter $ flutter pub add webview_flutter

34 class, along with the newly added

$ cd webview_in_flutter $ flutter pub add webview_flutter

44. In the next series of sections, you will add helper functions to

$ cd webview_in_flutter $ flutter pub add webview_flutter

50 that will, in turn, be invoked by the yet to be added menu items.

Get a list of all cookies

You are going to use JavaScript to get a list of all the cookies. To achieve this, add a helper method to the end of

$ cd webview_in_flutter $ flutter pub add webview_flutter

50 class, called

$ cd webview_in_flutter $ flutter pub add webview_flutter

55. Using the

$ cd webview_in_flutter $ flutter pub add webview_flutter

07 method, your helper method executes

$ cd webview_in_flutter $ flutter pub add webview_flutter

57 in the JavaScript context, returning a list of all cookies.

Add the following to the

$ cd webview_in_flutter $ flutter pub add webview_flutter

50 class:

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

0

Clear all cookies

To clear all the cookies in the WebView, use the

$ cd webview_in_flutter $ flutter pub add webview_flutter

59 method of the

$ cd webview_in_flutter $ flutter pub add webview_flutter

44 class. The method returns a

$ cd webview_in_flutter $ flutter pub add webview_flutter

61 that resolves to

$ cd webview_in_flutter $ flutter pub add webview_flutter

62 if the

$ cd webview_in_flutter $ flutter pub add webview_flutter

44 cleared the cookies, and

$ cd webview_in_flutter $ flutter pub add webview_flutter

64 if there were no cookies to clear.

Add the following to the

$ cd webview_in_flutter $ flutter pub add webview_flutter

50 class:

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

1

Adding a cookie can be done by invoking JavaScript. The API used to add a Cookie to a JavaScript document is .

Add the following to the

$ cd webview_in_flutter $ flutter pub add webview_flutter

50 class:

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

2

Cookies can also be set using the CookieManager as follows.

Add the following to the

$ cd webview_in_flutter $ flutter pub add webview_flutter

50 class:

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

3

Removing a cookie involves adding a cookie, with an expiry date set in the past.

Add the following to the

$ cd webview_in_flutter $ flutter pub add webview_flutter

50 class:

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

4

All that remains is to add the menu options, and wire them to the helper methods you just added. Update the

$ cd webview_in_flutter $ flutter pub add webview_flutter

50 class as follows:

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

5

Exercising the CookieManager

To use all the functionality you have just added to the app, try the following steps:

  1. Select List cookies. It should list the Google Analytics cookies set by flutter.dev.
  2. Select Clear cookies. It should report that the cookies were indeed cleared.
  3. Select Clear cookies again. It should report that no cookies were available to clear.
  4. Select List cookies. It should report that there are no cookies.
  5. Select Add cookie. It should report the cookie as added.
  6. Select Set cookie. It should report the cookie as set.
  7. Select List cookies, and then as a final flourish, select Remove cookie.

12. Load Flutter assets, files and HTML strings in the WebView

Your app can load HTML files using different methods and display them in the WebView. In this step you will load a Flutter asset specified in the

$ cd webview_in_flutter $ flutter pub add webview_flutter

70 file, load a file located at the specified path and load a page using a HTML String.

If you want to load a file located at a specified path, you will need to add the

$ cd webview_in_flutter $ flutter pub add webview_flutter

71 to the

$ cd webview_in_flutter $ flutter pub add webview_flutter

70. This is a Flutter plugin for finding commonly used locations on the filesystem.

On the command line, run the following command:

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

6

For loading the asset we need to specify the path to the asset in the

$ cd webview_in_flutter $ flutter pub add webview_flutter

70. In the

$ cd webview_in_flutter $ flutter pub add webview_flutter

70 add the following lines:

pubspec.yaml

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

7

To add the assets to your project, do the following steps:

  1. Create a new Directory with the name $ cd webview_in_flutter $ flutter pub add webview_flutter 75 in the root folder of your project.
  2. Create a new Directory with the name $ cd webview_in_flutter $ flutter pub add webview_flutter 76 in the $ cd webview_in_flutter $ flutter pub add webview_flutter 75 folder.
  3. Create a new Directory with the name $ cd webview_in_flutter $ flutter pub add webview_flutter 78 in the $ cd webview_in_flutter $ flutter pub add webview_flutter 76 folder.
  4. Create a new File with the name $ cd webview_in_flutter $ flutter pub add webview_flutter 80 in the $ cd webview_in_flutter $ flutter pub add webview_flutter 76 folder.
  5. Create a new File with the name $ cd webview_in_flutter $ flutter pub add webview_flutter 82 in the $ cd webview_in_flutter $ flutter pub add webview_flutter 78 folder.

Copy and paste the following code in the

$ cd webview_in_flutter $ flutter pub add webview_flutter

80 file:

assets/www/index.html

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

8

For the style.css use the following few lines to set the HTML header style:

assets/www/styles/style.css

android {
    //...
    defaultConfig {
        applicationId "com.example.webview_in_flutter"
        minSdkVersion 20                           // MODIFY
        targetSdkVersion flutter.targetSdkVersion
        versionCode flutterVersionCode.toInteger()
        versionName flutterVersionName
    }

9

Now that the assets are set and ready to use, you can implement the methods that are needed for loading and displaying Flutter assets, files or HTML Strings.

Load Flutter asset

For loading the asset you just created, all you need to do is call the

$ cd webview_in_flutter $ flutter pub add webview_flutter

85 method using the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9 and give as parameter the path to the asset. Add the following method at the end of your code:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

0

Load local file

For loading a file on your device you can add a method that will use the

$ cd webview_in_flutter $ flutter pub add webview_flutter

87 method, again by using the

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9 which takes a

$ cd webview_in_flutter $ flutter pub add webview_flutter

89 containing the path to the file.

You need to make a file containing the HTML code first. You can simply do this by adding the HTML code as a String at the top of your code in the

$ cd webview_in_flutter $ flutter pub add webview_flutter

90 file just beneath the imports.

lib/src/menu.dart

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

1

To create a

$ cd webview_in_flutter $ flutter pub add webview_flutter

91 and write the HTML String to the file you will add two methods. The

$ cd webview_in_flutter $ flutter pub add webview_flutter

92 will load the file by providing the path as a String which is returned by the

$ cd webview_in_flutter $ flutter pub add webview_flutter

93 method. Add the following methods to your code:

lib/src/menu.dart

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

2

Load HTML String

To display a page by providing a HTML string is pretty straight forward. The

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

9 has a method you can use called

$ cd webview_in_flutter $ flutter pub add webview_flutter

95 where you can give the HTML String as an argument. The

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

6 will then display the provided HTML page. Add the following method to your code:

lib/src/menu.dart

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

3

Now that the assets are set and ready for use, and the methods with all the functionality are made, the menu can be updated. Add the following entries to the

$ cd webview_in_flutter $ flutter pub add webview_flutter

35 enum:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

4

Now that the enum is updated you can add the menu options, and wire them to the helper methods you just added. Update the

$ cd webview_in_flutter $ flutter pub add webview_flutter

50 class as follows:

import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
  runApp(
    const MaterialApp(
      theme: ThemeData(useMaterial3: true),
      home: WebViewApp(),
    ),
  );
}
class WebViewApp extends StatefulWidget {
  const WebViewApp({super.key});
  @override
  State<WebViewApp> createState() => _WebViewAppState();
}
class _WebViewAppState extends State<WebViewApp> {
  late final WebViewController controller;
  @override
  void initState() {
    super.initState();
    controller = WebViewController()
      ..loadRequest(
        Uri.parse('https://flutter.dev'),
      );
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Flutter WebView'),
      ),
      body: WebViewWidget(
        controller: controller,
      ),
    );
  }
}

5

Testing the assets, file, and HTML string

To test if the code worked that you just implemented, you can run the code on your device and click on one of the newly added menu items. Notice how the

$ cd webview_in_flutter $ flutter pub add webview_flutter

99 uses the

$ cd webview_in_flutter $ flutter pub add webview_flutter

82 we added to change the header of the HTML file to the color blue.

Ios webview controller button next page on navigation top năm 2024

Ios webview controller button next page on navigation top năm 2024

13. All done!

Congratulations!!! You have completed the codelab. You can find the completed code for this codelab in the codelab repository.

To learn more, try the other Flutter codelabs.

Except as otherwise noted, the content of this page is licensed under the Creative Commons Attribution 4.0 License, and code samples are licensed under the Apache 2.0 License. For details, see the Google Developers Site Policies. Java is a registered trademark of Oracle and/or its affiliates.

[{ "type": "thumb-down", "id": "missingTheInformationINeed", "label":"Missing the information I need" },{ "type": "thumb-down", "id": "tooComplicatedTooManySteps", "label":"Too complicated / too many steps" },{ "type": "thumb-down", "id": "outOfDate", "label":"Out of date" },{ "type": "thumb-down", "id": "samplesCodeIssue", "label":"Samples / code issue" },{ "type": "thumb-down", "id": "otherDown", "label":"Other" }] [{ "type": "thumb-up", "id": "easyToUnderstand", "label":"Easy to understand" },{ "type": "thumb-up", "id": "solvedMyProblem", "label":"Solved my problem" },{ "type": "thumb-up", "id": "otherUp", "label":"Other" }]

What is the iOS equivalent of WebView?

WKWebView replaces the UIWebView class in iOS 8 and later, and it replaces the WebView class in macOS 10.10 and later. Embed a WKWebView object programmatically into your view hierarchy, or add it using Interface Builder.

How do I navigate from one page to another in XCode?

To set up page navigation, connect two or more interface controllers in your storyboard with next-page segues. Start by adding an interface controller for each page to the storyboard: Control-click the first interface controller and drag to the second interface controller.

What is the difference between WebView and WKWebView?

➤ The UIWebView uses UIKit framework while WKWebView uses WebKit. framework. ➤ The WKWebView loads web pages faster and more efficiently than UIWebView, and also doesn't have as much memory overhead for you. ➤ Scale pages to fit — this feature is available in UIWebView but not available in WKWebView.

How to add WebView in Swift?

Create a Web View | Xcode 12, Swift 5.

Step 1: Create a new View Controller. ... .

Step 2: Import the framework & Delegate. ... .

Step 3: Load the view. ... .

Step 4: Present the Web View. ... .

Step 5: Run your app!.