1

Flutterでシンプルなタブバーベースのアプリを作っています。と を使用CupertinoTabScaffoldCupertinoTabBarます。それぞれCupertinoTabViewに独自の がありWebViewます。

最初のには、クリックすると選択したタブが次のタブに変更され、ウィジェットを含むTabViewをロードし、特定の Web サイトの URL に移動するボタンが配置されます (URL は に書かれているのではなく、最初のタブから取得されることに注意してください)タブ)。CupertinoTabViewWebViewWebView:initialURL

問題は、コントローラーが割り当てられていないため、選択したタブが変更されている間にボタンをクリックするとWebView、特定の URL がロードされないことです。WebView

CupertinoTabView新しいウィジェットが完全に読み込まれるまでアプリを「待機」させるにはどうすればよいですか?

アプリを実行すると、エラーは次のようになります。

Unhandled Exception: NoSuchMethodError: The method 'navigateTo' was called on null.

これは、ボタンをクリックして次のコードを実行すると、行 tabController.index = tabIndexが有効になる前にkeyWebPage.curentState.navigateTo(まだnullである) が呼び出されるためと思われます。

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

WebPage.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が変更され、ボタンが複数回クリックされる可能性があるため、変数を渡すためにコンストラクターを使用することは考慮されていないことに注意してください。

4

0 に答える 0