SetState () в методе onTap (index) BottomNavigatonBar не перестраивает дерево виджетов - PullRequest
0 голосов
/ 24 июня 2019

Я пытаюсь подключить webview_flutter WebView к BottomNavigationBar. Я хочу, чтобы представление перезагружалось с новым URL при каждом касании вкладки. В обратный вызов onTap Я обновляю _currentUrl до нового URL и устанавливаю состояние вызова с новым индексом вкладки.

Почему панель вкладок обновляется, а веб-представление не перестраивается? Что я пропустил?

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 ]

1 голос
/ 24 июня 2019

Вы можете использовать WebViewController WebView для изменения URL веб-просмотра.

Добавить следующий код в ваш виджет WebView:

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

Теперь, после того, как вы присвоили WebViewController вашему экземпляру WebViewControllerВы можете изменить URL-адрес текущего веб-просмотра с помощью метода loadUrl () WebViewController

Так что вы можете изменить код вашего обработчика 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, но вы хотите изменить только URL в текущем сеансе WebView ...

0 голосов
/ 26 июня 2019

Спасибо за комментарий Джоэл

Да, довольно странно публиковать кроссплатформенный фреймворк, а базовые компоненты работают только на одной платформе, но, надеюсь, они исправят это до октября, как печально на их github ...

Я проверил свой пост, и WebView должен загрузить новый URL.Я забыл обновить _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() в конце обработчика onTap, который перестраивает страницу, но, как ни странно, WebView не будет повторно инициализирован !?Я думал, что это должно быть так, но флаттер должен так или иначе обрабатывать это ...

Также обратите внимание, что я переместил вашу переменную _currentTabIndex из вашего WebViewState класса в его верхний родительский класс WebViewApp.Проблема заключалась в том, что если вы перестраиваете страницу с помощью setState(), _currentTabIndex всегда будет инициализироваться заново с 0. Для обучения я просто переместил ее вверх, но, возможно, вы могли бы использовать ее как глобальный параметр ...

Но да, WebView все еще немного сбивает с толку, и в нем есть много различий между наборами iOS и Android WebView (в конце концов, трепетное WebView является «только» оберткой из текущего собственного набора WebView)

Надеюсь, это поможет и удачи!

...