【问题标题】:How to show Loading Indicator in WebView Flutter?如何在 WebView Flutter 中显示加载指示器?
【发布时间】:2019-11-05 14:52:44
【问题描述】:

我想在屏幕上显示 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);
          },
        ),
      )
    );
  }
}

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

【问题讨论】:

    标签: flutter webview loading


    【解决方案1】:

    完整示例

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

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

    【讨论】:

    • 如果以这种方式完成,WebView 是不可滚动的。返回 Stack() 而不是 Container() 的答案适用于我的情况。
    【解决方案2】:

    完成加载

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

    【讨论】:

    • 这对我有用,因为 Sanjayrajsinh 的另一个答案使用容器,这意味着您无法在 WebView 小部件中滚动网页。该解决方案在三元 else 中使用了 Stack,我现在可以在 WebView 中滚动网页。
    【解决方案3】:

    您能否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;
    }
    

    【讨论】:

      【解决方案4】:

      我们可以使用 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()),
            ),
          ]));
      

      【讨论】:

      • 不知道为什么,但这个解决方案似乎给我带来了很大的性能问题。需要注意的事项。
      【解决方案5】:

      只需使用堆栈和可见性小部件

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

      【讨论】:

        【解决方案6】:

        您可以使用 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();
                        },
                      ),
                    ],
                  ),
                ),
              ),
            );
          }
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2021-05-17
          • 2021-09-07
          • 2019-07-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多