BottomNavigatonBar的onTap(index)方法上的SetState()不会重建小部件树

时间:2019-06-24 15:03:01

标签: flutter flutter-layout setstate

我正在尝试将webview_flutter WebView连接到BottomNavigationBar。 我希望在每次点击选项卡时都使用新的URL重新加载视图。在 onTap回调程序将_currentUrl更新为新的URL,并使用新的标签索引调用设置状态。

为什么标签栏会更新,但Web视图不会重建? 我想念什么?

class WebViewApp extends StatefulWidget {
  @override
  State<StatefulWidget> createState() {
    return WebViewState();
  }
}

class WebViewState extends State<WebViewApp> {
  int _currentTabIndex = 0;
  String _currentUrl = URL.home;

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter WebView Demo',
      home: Scaffold(
        body: WebView(initialUrl: _currentUrl),
        bottomNavigationBar: BottomNavigationBar(
          currentIndex: _currentTabIndex,
          items: [
            BottomNavigationBarItem(
              icon: Icon(Icons.home),
              title: Text('Home'),
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.search),
              title: Text('Search'),
            ),
            BottomNavigationBarItem(
              icon: Icon(Icons.calendar_today),
              title: Text('Profile'),
            ),
          ],
          onTap: (index) {
            switch (index) {
              case 0:
                _currentUrl = URL.home;
                break;
              case 1:
                _currentUrl = URL.search;
                break;
              case 2:
                _currentUrl = URL.calendar;
                break;
            }
            setState(() {
              _currentTabIndex = index;
            });
          },
        ),
      ),
    );
  }
}

2 个答案:

答案 0 :(得分:1)

您可以使用WebView的WebViewController更改Webview的网址

将以下代码添加到您的WebView小部件:

body: WebView(
  initialUrl: _currentUrl,
  onWebViewCreated: (WebViewController webController) {
    _webController = webController;
  },
),

现在,在将WebViewController关联到您的WebViewController实例之后,您可以使用WebViewController的loadUrl()方法更改当前Webview的URL

因此您可以将onTap处理程序的代码更改为以下代码:

onTap: (index) {
  switch (index) {
    case 0:
      _webController.loadUrl('your_home_url');
    break;
    case 1:
      _webController.loadUrl('your_search_url');
    break;
    case 2:
      _webController.loadUrl('your_calander_url');
    break;
  }
},

WebViews和setState的问题在于将重新构建整个Widget / Page,包括WebView的实例,但是您只想更改当前WebView会话中的url ...

答案 1 :(得分:0)

感谢Joel的评论

是的,发布跨平台框架和基本组件只能在一个平台上工作是很奇怪的,但是,希望他们能够修复到十月份,直到他们在github上感到悲伤为止。

我检查了我的帖子,WebView应该加载新的URL。我忘记的是在导航的void Start() { //create your materials var yourMaterials = new Material[] { Mat1, Mat2 }; //assign it go.GetComponent<Renderer>().materials = yourMaterials ; } 处理程序中更新_currentTabIndex

但是无论如何:我举了一个简短的例子说明你的情况。对我来说很好...

onTap

请注意,我在import 'package:flutter/material.dart'; import 'package:flutter/widgets.dart'; import 'package:webview_flutter/webview_flutter.dart'; void main() => runApp(MyApp()); class MyApp extends StatelessWidget { @override Widget build(BuildContext context) { return MaterialApp( title: 'WebView App', debugShowCheckedModeBanner: false, home: WebPage(), ); } } class WebPage extends StatefulWidget { int currentTabIndex = 0; @override _WebPageState createState() => _WebPageState(); } class _WebPageState extends State<WebPage> { List<String> _urls = [ 'https://www.zdf.de/nachrichten/heute/rubrik-politik-100.html', 'https://www.zdf.de/nachrichten/heute/rubrik-wirtschaft-100.html', 'https://www.zdf.de/nachrichten/heute/rubrik-panorama-100.html' ]; WebViewController _webController; @override Widget build(BuildContext context) { print('<----- build init ----->'); return Scaffold( appBar: AppBar( centerTitle: true, title: Text('WebView'), ), body: WebView( initialUrl: _urls[widget.currentTabIndex], javascriptMode: JavascriptMode.unrestricted, onWebViewCreated: (WebViewController webController) { _webController = webController; }, ), bottomNavigationBar: BottomNavigationBar( currentIndex: widget.currentTabIndex, items: [ BottomNavigationBarItem( icon: Icon(Icons.people), title: Text('Politik') ), BottomNavigationBarItem( icon: Icon(Icons.public), title: Text('Wirtschaft') ), BottomNavigationBarItem( icon: Icon(Icons.pie_chart_outlined), title: Text('Panorama') ) ], onTap: (selectedIndex) { _webController.loadUrl(_urls[selectedIndex]); setState(() { widget.currentTabIndex = selectedIndex; }); }, ), ); } } 处理程序的末尾调用了setState(),该处理程序重建了页面,但是很遗憾,WebView不会重新初始化!我以为一定是这样,但是颤动一定是在某种程度上处理了这个问题……

还要注意,我将您的onTap变量从您的_currentTabIndex类移到了其上级父类WebViewState。问题是,如果您通过WebViewApp重建页面,则setState()始终将初始化为0。出于教程的缘故,我只是将其向上移动,但也许可以将其用作全局参数。

但是,是的,WebView仍然有点令人困惑,并且iOS和Android WebView套件之间有很多差异(归根结底,颤抖的WebView只是当前本机WebView套件的包装)。 / p>

我希望这会有所帮助,祝你好运!