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

时间:2019-11-05 14:52:44

标签: flutter webview loading

我想在屏幕上显示的Web视图数据之前先显示“正在加载”。该怎么办?

这是我的代码:

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);
          },
        ),
      )
    );
  }
}

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

5 个答案:

答案 0 :(得分:4)

完成加载

后访问 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(),
        ],
      ),
    );
  }

}

答案 1 :(得分:3)

我只使用.row-div { display: flex; justify-content: center; } /* Having some margin to make the two divs some distance */ .row-div>div { margin-right: 5px; } 小部件,因此在Webview顶部设置了加载指示器。调用webview的Stack时,我设置了onPageFinished变量值并设置了透明容器。

isLoading=false

答案 2 :(得分:2)

您可以 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;
}

答案 3 :(得分:0)

我们可以使用 IndexedStack 小部件帮助根据索引切换小部件。我们还利用了 webview 的 onPageStarted 和 onPageFinished 属性。使用状态管理,我们在页面开始加载和页面加载完成时更改索引的值。

num pos = 1;

在构建方法中

return Scaffold(
        body: IndexedStack(index: pos, children: <Widget>[
      WebView(
        initialUrl: 'http://pub.dev/',
        javascriptMode: JavascriptMode.unrestricted,
        onPageStarted: (value) {
          setState(() {
            pos = 1;
          });
        },
        onPageFinished: (value) {
          setState(() {
            pos = 0;
          });
        },
      ),
      Container(
        child: Center(child: CircularProgressIndicator()),
      ),
    ]));

答案 4 :(得分:0)

您可以使用 BLOC、Stream 和无状态小部件


import 'dart:async';

import 'package:rxdart/subjects.dart';

class LoadingWebPageBloc  {
//Controllers
  final BehaviorSubject<bool> _loadingWebPageController = BehaviorSubject<bool>.seeded(true);

  //Sinks
  Function(bool) get changeLoadingWebPage => _loadingWebPageController.sink.add;

  //Streams
  Stream<bool> get loadingWebPageStream => _loadingWebPageController.stream.asBroadcastStream();

  @override
  void dispose() {
    _loadingWebPageController.close();
    super.dispose();
  }
}

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

class CustomWebPagePreview extends StatelessWidget {
  final String url;
  CustomWebPagePreview({@required this.url});

  final LoadingWebPageBloc loadingWebPageBloc = LoadingWebPageBloc();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: appBar,
        body: Container(
          child: Stack(
            children: <Widget>[
              WebView(
                initialUrl: url,
                javascriptMode: JavascriptMode.unrestricted,
                onPageStarted: (value) {
                  loadingWebPageBloc.changeloading(true);
                },
                onPageFinished: (value) {
                  loadingWebPageBloc.changeloading(false);
                },
              ),
              StreamBuilder<bool>(
                stream: loadingWebPageBloc.loading,
                initialData: true,
                builder: (context, snap) {
                  if (snap.hasData && snap.data == true) {
                    return Center(
                      child: CircularProgressIndicator(),
                    );
                  }
                  return SizedBox();
                },
              ),
            ],
          ),
        ),
      ),
    );
  }
}