如何在 WebView Flutter 中显示加载指示器?

R R*_*ara 16 loading webview flutter

我想在屏幕上显示 Web 视图数据之前先显示 Loading。怎么能这样?

这是我的代码:

class WebDetailPage extends StatelessWidget {
  final String title;
  final String webUrl;

  final Completer<WebViewController> _controller =
      Completer<WebViewController>();

  WebDetailPage({
    @required this.title,
    @required this.webUrl,
  });

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        backgroundColor: Colour.white,
        title: Text(title, style: TextStyle(color: Colour.midnightBlue)),
        leading: IconButton(
            icon: Icon(Icons.arrow_back, color: Colour.midnightBlue),
            onPressed: () => Navigator.of(context).pop()),
      ),
      body: Center(
        child: WebView(
          initialUrl: webUrl,
          javascriptMode: JavascriptMode.unrestricted,
          onWebViewCreated: (WebViewController webViewController) {
            _controller.complete(webViewController);
          },
        ),
      )
    );
  }
}
Run Code Online (Sandbox Code Playgroud)

有人可以帮我解决这个问题吗?因为我已经搜索和研究过它仍然可以找到解决方案。

San*_*inh 44

完整示例

class WebViewState extends State<WebViewScreen>{

  String title,url;
  bool isLoading=true;
  final _key = UniqueKey();
  
  WebViewState(String title,String url){
    this.title=title;
    this.url=url;
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
          title: Text(this.title,style: TextStyle(fontWeight: FontWeight.w700)),centerTitle: true
      ),
      body: Stack(
        children: <Widget>[
          WebView(
            key: _key,
            initialUrl: this.url,
            javascriptMode: JavascriptMode.unrestricted,
            onPageFinished: (finish) {
              setState(() {
                isLoading = false;
              });
            },
          ),
          isLoading ? Center( child: CircularProgressIndicator(),)
                    : Stack(),
        ],
      ),
    );
  }

}
Run Code Online (Sandbox Code Playgroud)

我只是Stack在 webview 设置加载指示器之上使用小部件。当调用onPageFinishedwebview 时,我设置了isLoading=false变量值并设置了透明容器。


小智 6

如果有人使用 webview_flutter 版本 4.0.2 偶然发现这个问题,我们必须使用WebViewControllersetNavigationDelegate设置 onPageFinished 回调。

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

class PrivacyPolicyPage extends StatefulWidget {
  static const routeName = "/privacy_policy";

  const PrivacyPolicyPage({super.key});

  @override
  State<PrivacyPolicyPage> createState() => _PrivacyPolicyPageState();
}

class _PrivacyPolicyPageState extends State<PrivacyPolicyPage> {
  late final WebViewController _controller;
  bool _loading = true;

  @override
  void initState() {
    _controller = WebViewController.fromPlatformCreationParams(
        const PlatformWebViewControllerCreationParams())
      ..setNavigationDelegate(NavigationDelegate(
          onPageFinished: (_) => setState(() {
                _loading = false;
              })))
      ..setJavaScriptMode(JavaScriptMode.disabled)
      ..loadFlutterAsset("assets/privacy_policy.html");
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Privacy Policy')),
      body: Stack(children: [
        WebViewWidget(controller: _controller),
        if (_loading) const Center(child: CircularProgressIndicator())
      ]),
    );
  }
}

Run Code Online (Sandbox Code Playgroud)


Yas*_*ash 5

你可以用Future Builder轻松解决这个问题。是的,你没听错。

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

void main() => runApp(MaterialApp(home: MyApp()));

class MyApp extends StatelessWidget {

  static Future<String> get _url async {
    await Future.delayed(Duration(seconds: 1));
    return 'https://flutter.dev/';
  }

  @override
  Widget build(BuildContext context) => Scaffold(
    body: Center(
      child:FutureBuilder(
        future: _url,
        builder: (BuildContext context, AsyncSnapshot snapshot) => snapshot.hasData
        ? WebViewWidget(url: snapshot.data,)
        : CircularProgressIndicator()),
  ),);
}

class WebViewWidget extends StatefulWidget {
  final String url;
  WebViewWidget({this.url});

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

class _WebViewWidget extends State<WebViewWidget> {
  WebView _webView;
  @override
  void initState() {
    super.initState();
     _webView = WebView(
      initialUrl: widget.url,
      javascriptMode: JavascriptMode.unrestricted,
    );
  }

  @override
  void dispose() {
    super.dispose();
    _webView = null;
  }

  @override
  Widget build(BuildContext context) => _webView;
}
Run Code Online (Sandbox Code Playgroud)


Nik*_*ani 5

加载完成后访问WebView

class WebViewState extends State<WebViewScreen>{

  String title,url;
  bool isLoading=true;
  final _key = UniqueKey();

  WebViewState(String title,String url){
    this.title=title;
    this.url=url;
  }
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: new AppBar(
          title: Text(this.title,style: TextStyle(fontWeight: FontWeight.w700)),centerTitle: true
      ),
      body: Stack(
        children: <Widget>[
          WebView(
            key: _key,
            initialUrl: this.url,
            javascriptMode: JavascriptMode.unrestricted,
            onPageFinished: (finish) {
              setState(() {
                isLoading = false;
              });
            },
          ),
          isLoading ? Center( child: CircularProgressIndicator(),)
                    : Stack(),
        ],
      ),
    );
  }

}
Run Code Online (Sandbox Code Playgroud)


Rac*_*era 5

只需使用 Stack 和 Visibility Widget

import 'dart:io';

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

class MyWebView extends StatefulWidget {
final String url;
const MyWebView({Key? key, this.url = ''}) : super(key: key);

@override
State<MyWebView> createState() => _MyWebViewState();
}

class _MyWebViewState extends State<MyWebView> {
  bool isLoading = true;
  @override
  void initState() {
  super.initState();
  if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
  if (Platform.isIOS) WebView.platform = CupertinoWebView();
}

@override
Widget build(BuildContext context) {
return SafeArea(
  child: Scaffold(
    appBar: AppBar(
      backgroundColor: Colors.transparent,
      elevation: 0,
    ),
    body: Stack(
      children: [
        WebView(
          initialUrl: widget.url,
          onPageFinished: (finish) {
            setState(() {
              isLoading = false;
            });
          },
          javascriptMode: JavascriptMode.unrestricted,
        ),
        Visibility(
          visible: isLoading,
          child: const Center(
            child: CircularProgressIndicator(),
          ),
        )
      ],
    ),
    bottomNavigationBar: BottomAppBar(
      child: Row(),
      ),
    ),
  );
 }
}
Run Code Online (Sandbox Code Playgroud)


gen*_*ser 5

Google Codelab 示例

在我看来,这个解决方案是最简单的,并且具有很好的用户体验

更多信息请查看官方示例Listening for page load events

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;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        WebView(
          initialUrl: 'https://flutter.dev',
          onPageStarted: (url) {
            setState(() {
              loadingPercentage = 0;
            });
          },
          onProgress: (progress) {
            setState(() {
              loadingPercentage = progress;
            });
          },
          onPageFinished: (url) {
            setState(() {
              loadingPercentage = 100;
            });
          },
        ),
        if (loadingPercentage < 100)
          LinearProgressIndicator(
            value: loadingPercentage / 100.0,
          ),
      ],
    );
  }
}
Run Code Online (Sandbox Code Playgroud)