BottomNavigationBar nu arată fila curentă atunci când utilizați widget-ul offStageNavigator

voturi
0

Am încercat să construiască o în bottomNavigationBarcazul în care fiecare tabItem va menține propriul stat de navigație.

Am 5 nav elemente: enum TabItem { top_stories, topics, special_reports, more }. Pentru cel de 1 Sunt folosind HomeScreenwidget - ul pentru a afișa o listă de articole. Fiecare articol poate fi făcut clic pe pentru a afișa conținutul integral al acesteia. Pentru a 2 - tabItem (subiecte), aș dori să afișați o altă listă de articole , dar acum eu sunt , folosind TopicScreenwidget - ul pentru a arăta un simplu Textcâmp.

În mea NewsApp, eu sunt , folosind un Stackși un Offstagewidget din jurul meu Navigatorclasă pentru fiecare dintre tabItems.

Pentru primul tabItemtotul funcționează OK. Când fac clic pe , topicsdeși, eu nu văd conținutul respectiv TopicScreenwidget - ul , dar toata lista de articole este afișat din nou. Lucru ciudat este că această listă pare a fi creat din nou , de la zero pentru acest tabItem. Pot selecta perfect un alt articol pentru fiecare tabItem, naviga prin toate bottomNavOptions și aplicația va „aminti“ alegerile mele.

În codul:

NewsApp.dart

import 'package:flutter/material.dart';
import 'package:news_app/navigation/bottom_navigation.dart';
import 'package:news_app/navigation/tab_navigator.dart';

class NewsApp extends StatefulWidget {
//  NewsApp({Key key}) : super(key: key);

  @override
  _NewsAppState createState() => _NewsAppState();
}

class _NewsAppState extends State<NewsApp> {
  /// Give a unique key to each one of the bottom navigation tab items
  Map<TabItem, GlobalKey<NavigatorState>> _navigatorKeys = {
    TabItem.top_stories: GlobalKey<NavigatorState>(),
    TabItem.topics: GlobalKey<NavigatorState>(),
    TabItem.special_reports: GlobalKey<NavigatorState>(),
    TabItem.more: GlobalKey<NavigatorState>(),
  };
  TabItem currentTab = TabItem.top_stories;

  /// This function is passed to the onTap callback upon clicking on a [tabItem].
  void _selectTab(TabItem tabItem) {
    setState(() {
      currentTab = tabItem;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('AppNews.gr'),
        elevation: 0.1,
      ),

      /// Making tab navigation stateful. Stack all tab items, fade-in the selected
      /// view and fade out the rest (unselected - _currentTab != tabItem). The
      /// faded out views are laid out in the widget tree but not painted and are
      /// modeled with the offstage property.
      body: Stack(children: <Widget>[
        _buildOffStageNavigator(TabItem.top_stories),
        _buildOffStageNavigator(TabItem.topics),
        _buildOffStageNavigator(TabItem.special_reports),
        _buildOffStageNavigator(TabItem.more)
      ]),
      bottomNavigationBar:
          BottomNavigation(currentTab: currentTab, onSelectTab: _selectTab),
    );
  }

  /// This function wraps each [tabItem] into each own [TabNavigator]
  Widget _buildOffStageNavigator(TabItem tabItem) {
    return Offstage(
        offstage: currentTab != tabItem,
        child: TabNavigator(
          navigatorKey: _navigatorKeys[tabItem],
          tabItem: tabItem,
        ));
  }
}

TabNavigator.dart

import 'package:flutter/material.dart';
import 'package:news_app/navigation/routes.dart';
import 'package:news_app/models/articles.dart';
import 'package:news_app/navigation/bottom_navigation.dart';
import 'package:news_app/screens/Home/home_screen.dart';
import 'package:news_app/screens/Detail/detail_screen.dart';
import 'package:news_app/screens/Topics/topic_screen.dart';

/// A navigator class used to perform routing and state management among different
/// [tabItem]s. Uses a unique [navigatorKey] to track the state of the
/// [TabNavigator] object across the app.
class TabNavigator extends StatelessWidget {
  final GlobalKey<NavigatorState> navigatorKey;
  final TabItem tabItem;

  TabNavigator({this.navigatorKey, this.tabItem});

  /// A method used to push a detail route in a specific [context].
  void _push(BuildContext context, {Article article}) {
    var routeBuilder = _routeBuilder(context, specArticle: article);

    Navigator.push(
        context,
        MaterialPageRoute(
            builder: (context) => routeBuilder[Routes.detail](context)));
  }

  /// A method to be passed to the route generator callback (onGenerateRoute)
  /// when the app is navigated to a named route.
  Map<String, WidgetBuilder> _routeBuilder(BuildContext context,
      {Article specArticle}) {
    return {
      ///The home screen containing all articles('/')
      Routes.home: (context) => HomeScreen(
            onPush: (specArticle) => _push(context, article: specArticle),
          ),

      ///The detail screen of a specific article('/detail')
      Routes.detail: (context) => DetailScreen(article: specArticle),

      ///The topics screen of all the available topics('/topics')
      Routes.topics: (context) => TopicScreen(), /// <-- THIS DOESN'T SEEM TO WORK. 
    };
  }

  @override
  Widget build(BuildContext context) {
    final routeBuilders = _routeBuilder(context);

    return Navigator(
        key: navigatorKey,
        initialRoute: Routes.home,
        onGenerateRoute: (RouteSettings routeSettings) {
          return MaterialPageRoute(
              settings: routeSettings,
              builder: (context) => routeBuilders[routeSettings.name](context));
        });
  }
}

BottomNavigation.dart

import 'package:flutter/material.dart';
import 'package:news_app/screens/Home/Style/home_style.dart';

/// An enum struct of all the different bottom navigation items.
enum TabItem { top_stories, topics, special_reports, more }

/// A class built on BottomNavigationBar widget used to navigate among the app's
/// [tabItem]s. Defines static const Map<[tabItem], String>s to associate a tab
/// with a material icon.
class BottomNavigation extends StatelessWidget {
  final TabItem currentTab;
  final ValueChanged<TabItem> onSelectTab;

  static const Map<TabItem, String> tabName = {
    TabItem.top_stories: 'Top Stories',
    TabItem.topics: 'Topics',
    TabItem.special_reports: 'Special Reports',
    TabItem.more: 'More',
  };

  static const Map<TabItem, Icon> tabIcon = {
    TabItem.top_stories: Icon(Icons.subject),
    TabItem.topics: Icon(Icons.format_list_bulleted),
    TabItem.special_reports: Icon(Icons.filter_none),
    TabItem.more: Icon(Icons.more_horiz),
  };

  BottomNavigation({this.currentTab, this.onSelectTab});

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      ///Fixed type is the default when there are less than four items.
      ///The selected item is rendered with the selectedItemColor if it's non-null,
      ///otherwise the theme's ThemeData.primaryColor is used.
//      type: BottomNavigationBarType.shifting,
      items: [
        _buildItem(
            TabItem.top_stories, BottomNavigation.tabIcon[TabItem.top_stories]),
        _buildItem(TabItem.topics, BottomNavigation.tabIcon[TabItem.topics]),
        _buildItem(TabItem.special_reports,
            BottomNavigation.tabIcon[TabItem.special_reports]),
        _buildItem(TabItem.more, BottomNavigation.tabIcon[TabItem.more]),
      ],
      onTap: (index) => onSelectTab(
        TabItem.values[index],
      ),
      selectedItemColor: bottomNavBarItemsColor,
    );
  }

  BottomNavigationBarItem _buildItem(TabItem tabItem, Icon tabIcon) {
    String text = BottomNavigation.tabName[tabItem];
    return BottomNavigationBarItem(
        icon: tabIcon,
        title: Text(text),
        backgroundColor: bottomNavBarBackgroundColor);
  }
}

HomeScreen.dart

import 'package:flutter/material.dart';
import 'package:news_app/models/articles.dart';
import 'package:news_app/models/tags.dart';
import 'package:news_app/screens/Home/Style/home_style.dart';
import 'package:news_app/widgets/article_card.dart';

/// The home screen widget that shows the list of [articles]
class HomeScreen extends StatefulWidget {
  final ValueChanged onPush;

  HomeScreen({Key key, this.onPush}) : super(key: key);

  @override
  _HomeScreenState createState() => _HomeScreenState(onPushCard: onPush);
}

class _HomeScreenState extends State<HomeScreen> {
  List articles;
  final ValueChanged onPushCard;

  _HomeScreenState({this.onPushCard});

  /// Dummy fetch the list of articles (will be swapped out for the api version)
  @override
  void initState() {
    articles = getDummyArticles();
    super.initState();
  }

  @override
  Widget build(BuildContext context) {
    return SafeArea(
        //TODO-me: Research if this is actually needed
        child: ListView.builder(
            //shrinkWrap: true, //TODO-me: Test this
            itemCount: articles.length, //TODO-me: Remove to scroll infinitely
            itemBuilder: (BuildContext context, int index) {
              return ArticleCard(
                  cardElevation: articleTileElevation,
                  cardMargin: articleTileMargin,
                  cardDecoration: articleTileDecoration,
                  cardTilePadding: articleTilePadding,
                  cardTextTitleStyle: articleTileTitleStyle,
                  cardTextSubHeaderStyle: articleTileSubHeaderStyle,
                  cardArticle: articles[index],
                  pushCardAction: onPushCard);
            }));
  }

  @override
  void dispose() {
    super.dispose();
  }
}

//TODO-me: Dummy list of articles. 
List getDummyArticles() {
  /// A static list of Articles
}

TopicScreen.dart

import 'package:flutter/material.dart';

class TopicScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Container(
        child: Text('Hello Topics'),
      ),
    );
  }
}
Întrebat 09/10/2019 la 12:58
sursa de către utilizator
În alte limbi...                            

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more