首页 > 解决方案 > 更改标签控制器索引,等待 Flutter 中的 TabView

问题描述

我正在使用 Flutter 制作一个基于标签栏的简单应用程序。它使用CupertinoTabScaffoldCupertinoTabBar。每个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 将被更改,并且单击按钮可以不止一次。

标签: flutterdartfutureflutter-cupertino

解决方案


推荐阅读