可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I'm using the webview_fluttter plugin, but I can't find a way to show a CircularProgressIndicator before the webview shows the page...
What's the equivalent of Androids WebViewClient onPageStarted/onPageFinished?
WebView(
initialUrl: url,
onWebViewCreated: (controller) {
},
)
thank you
回答1:
In version 0.3.5 there is 'onPageFinished' callback. You can create WebView container with IndexedStack.
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class _WebViewContainerState extends State < WebViewContainer > {
var _url;
final _key = UniqueKey();
_WebViewContainerState(this._url);
num _stackToView = 1;
void _handleLoad(String value) {
setState(() {
_stackToView = 0;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: IndexedStack(
index: _stackToView,
children: [
Column(
children: < Widget > [
Expanded(
child: WebView(
key: _key,
javascriptMode: JavascriptMode.unrestricted,
initialUrl: _url,
onPageFinished: _handleLoad,
)
),
],
),
Container(
color: Colors.white,
child: Center(
child: CircularProgressIndicator(),
),
),
],
)
);
}
}
class WebViewContainer extends StatefulWidget {
final url;
WebViewContainer(this.url);
@override
createState() => _WebViewContainerState(this.url);
}
回答2:
class _WebViewContainerState extends State<WebViewContainer> {
var _url;
final _key = UniqueKey();
bool _isLoadingPage;
Completer<WebViewController> _controller = Completer<WebViewController>();
_WebViewContainerState(this._url);
@override
void initState() {
super.initState();
_isLoadingPage = true;
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
new WebView(
key: _key,
initialUrl: _url,
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (webViewCreate) {
_controller.complete(webViewCreate);
},
onPageFinished: (finish) {
setState(() {
_isLoadingPage = false;
});
},
),
_isLoadingPage
? Container(
alignment: FractionalOffset.center,
child: CircularProgressIndicator(),
)
: Container(
color: Colors.transparent,
),
],
),
);
}
}
回答3:
This is working properly for me
initState() {
isLoading = true;
};
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: new AppBar(
title: Text("Your Title",centerTitle: true
),
body: Stack(
children: <Widget>[
new WebView(
initialUrl: /* YourUrl*/,
onPageFinished: (_) {
setState(() {
isLoading = false;
});
},
),
isLoading ? Center( child: CircularProgressIndicator()) : Container(),
],
),
);
}
回答4:
Optional parameters hidden and initialChild are available so that you can show something else while waiting for the page to load.If you set hidden to true it will show a default CircularProgressIndicator. If you additionally specify a Widget for initialChild you can have it display whatever you like till page-load.
check this page : flutter_webview_plugin
and you can specify what you want to show with initialChild
return new MaterialApp(
title: 'Flutter WebView Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
routes: {
'/': (_) => const MyHomePage(title: 'Flutter WebView Demo'),
'/widget': (_) => new WebviewScaffold(
url: selectedUrl,
appBar: new AppBar(
title: const Text('Widget webview'),
),
withZoom: true,
withLocalStorage: true,
hidden: true,
initialChild: Container(
child: const Center(
child: CircularProgressIndicator(),
),
),
),
},
);
回答5:
I use a combination of webview_flutter, progress_indicators
Here is a sample working code:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';
import 'package:progress_indicators/progress_indicators.dart';
class ContactUs extends StatefulWidget {
@override
_ContactUsState createState() => _ContactUsState();
}
class _ContactUsState extends State<ContactUs> {
bool vis1 = true;
Size deviceSize;
@override
Widget build(BuildContext context) {
deviceSize = MediaQuery.of(context).size;
final lindicator = Center(
child: AnimatedOpacity(
// If the Widget should be visible, animate to 1.0 (fully visible). If
// the Widget should be hidden, animate to 0.0 (invisible).
opacity: vis1 ? 1.0 : 0.0,
duration: Duration(milliseconds: 500),
// The green box needs to be the child of the AnimatedOpacity
child: HeartbeatProgressIndicator(
child: Container(
width: 100.0,
height: 50.0,
padding: EdgeInsets.fromLTRB(35.0,0.0,5.0,0.0),
child: Row(
children: <Widget>[
Icon(
Icons.all_inclusive, color: Colors.white, size: 14.0,),
Text(
"Loading View", style: TextStyle(color: Colors.white, fontSize: 6.0),),
],
),
),
),
),
);
return new Scaffold(
appBar: new AppBar(
title: new Row(
children:<Widget>[
Text('THisApp'),
lindicator,
]),
backgroundColor: Colors.red,
),
body: new Container(
child:WebView(
initialUrl: 'https://cspydo.com.ng/',
javaScriptMode: JavaScriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController){
setState(() {
vis1=false;
});
},
)
),
);
}
}
回答6:
You can use my plugin flutter_inappwebview, which has a lot of events, methods, and options compared to other plugins, combined with IndexedStack
and switch between widgets after the WebView is loaded using onLoadStop
.
Full example:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
@override
void initState() {
super.initState();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: InAppWebViewPage()
);
}
}
class InAppWebViewPage extends StatefulWidget {
@override
_InAppWebViewPageState createState() => new _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
InAppWebViewController webView;
int _page = 1;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("InAppWebView")
),
body: IndexedStack(
index: _page,
children: <Widget>[
InAppWebView(
initialUrl: "https://flutter.dev",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true,
),
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
setState(() {
_page = 0;
});
},
),
Container(
child: const Center(
child: CircularProgressIndicator(),
),
),
],
),
);
}
}
回答7:
You can work on isLoading and change it after you are sure data is loaded properly.
class X extends StatefulWidget {
XState createState() => XState();
}
class XState extends State<X>{
bool isLoading = false;
@override
void initState() {
setState(() {
isLoading = true;
});
super.initState();
}
Widget build(BuildContext context) {
return Scaffold(
body: Column(
children: <Widget>[
isLoading ? Center(child: CircularProgressIndicator()) : WebView(...)
]
)
);
}
}
回答8:
Found the solution.You can add initialChild and set attribute hidden as true.
WebviewScaffold(
hidden: true,
url:url,initialChild: Center(
child: Text("Plase Wait...",style: TextStyle(
fontWeight: FontWeight.bold,
color: Colors.deepPurpleAccent[100]
),)
) )