我正在使用 Flutter 制作一个基于标签栏的简单应用程序。它使用CupertinoTabScaffold
和CupertinoTabBar
。每个CupertinoTabView
都有自己的WebView
.
在第一个TabView
中,放置一个按钮,如果单击所选选项卡将更改为下一个以加载CupertinoTabView
包含WebView
小部件的选项卡,然后导航到某个网站 URL(请注意,该 URL 不是写在上面WebView:initialURL
,而是从第一个标签)。
问题是,当单击按钮时,在更改选定选项卡时,由于未分配控制器而WebView
不会加载特定的URL 。WebView
如何让应用程序“等待”新CupertinoTabView
小部件完全加载?
如果我运行该应用程序,则错误如下:
Unhandled Exception: NoSuchMethodError: The method 'navigateTo' was called on null.
这似乎是因为当单击按钮执行以下代码时,在该行将 tabController.index = tabIndex
生效之前,keyWebPage.curentState.navigateTo
(尚未为空)被调用。
tabController.index = tabIndex;
keyWebPage.currentState.navigateTo(url); //executed 'before' the new TabView initialization
我怀疑这个问题的原因,但无法弄清楚如何解决它。
main.dart
final GlobalKey<PageWebState> keyWebPage = GlobalKey();
class _MyHomePageState extends State<MyHomePage> {
final CupertinoTabController tabController = CupertinoTabController();
int _currentTabIndex = 0;
WebPage pageWeb;
@override
void initState() {
super.initState();
pageWeb = new PageWeb(
this,
key: keyWebPage,
);
}
void navigateTab(int tabIndex, String url) {
setState(() {
_currentTabIndex = tabIndex;
tabController.index = tabIndex;
// HERE is the error occurring part
keyWebPage.currentState.navigateTo(url);
});
}
@override
Widget build(BuildContext context) {
final Widget scaffold = CupertinoTabScaffold(
controller: tabController,
tabBar: CupertinoTabBar(
currentIndex: _currentTabIndex,
onTap: (index) {
setState(() {
_currentTabIndex = index;
});
},
items: const <BottomNavigationBarItem>[
const BottomNavigationBarItem(icon: const Icon(Icons.home), title: Text('Start')),
const BottomNavigationBarItem(icon: const Icon(Icons.web), title: Text('Webpage')),
],
),
tabBuilder: (context, index) {
CupertinoTabView _viewWidget;
switch (index) {
case 0:
_viewWidget = CupertinoTabView(
builder: (context) {
return Center(
child: CupertinoButton(
child: Text('Navigate'),
onPressed: () {
navigateTab(1, 'https://stackoverflow.com/');
},
),
);
},
);
break;
case 1:
_viewWidget = CupertinoTabView(
builder: (context) {
return pageWeb;
},
);
break;
}
return _viewWidget;
},
);
return scaffold;
}
}
网页.dart
final Completer<WebViewController> _controller = Completer<WebViewController>();
class PageWeb extends StatefulWidget {
final delegate;
final ObjectKey key;
PageWeb(this.delegate, this.key);
@override
PageWebState createState() {
return PageWebState();
}
}
void navigateTo(String url) { //Function that will be called on main.dart
controller.future.then((controller) => controller.loadUrl(url));
}
class PageWebState extends State<PageWeb> {
@override
Widget build(BuildContext context) {
return CupertinoPageScaffold(
navigationBar: CupertinoNavigationBar(
middle: Text("Test"),
),
child: SafeArea(
child: Container(
child: new WebView(
key: widget.key,
initialUrl: "https://www.google.com/",
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
))));
}
}
请注意,不考虑使用构造函数传递变量,因为 URL 将被更改,并且单击按钮可以不止一次。