BottomNavigationBar niet de huidige tab te tonen bij gebruik van de offStageNavigator widget

stemmen
0

Ik ben op zoek naar een te bouwen bottomNavigationBarwaar elke tabItem zal zijn eigen navigatie-status te behouden.

Ik heb 5 nav items: enum TabItem { top_stories, topics, special_reports, more }. Voor de 1e degene die ik ben met behulp van de HomeScreenwidget om een lijst met artikelen weer te geven. Elk artikel kan worden geklikt om de volledige inhoud te tonen. Voor de 2e tabItem (onderwerpen), zou ik graag een andere lijst met items weer te geven, maar voor nu ben ik met behulp van de TopicScreenwidget om een eenvoudige tonen Textveld.

In mijn NewsApp, ben ik met behulp van een Stacken een Offstagewidget om mijn Navigatorklasse voor elk van de tabItems.

Voor de 1e tabItemalles werkt OK. Wanneer ik op topicsal, weet ik niet de inhoud van de respectieve zien TopicScreenwidget, maar de hele lijst van artikelen wordt opnieuw weergegeven. Het rare is dat deze lijst lijkt om opnieuw te worden gemaakt vanuit het niets voor deze tabItem. Ik kan perfect selecteer een ander artikel voor elke tabItem, navigeren door alle bottomNavOptions en de app zal herinneren mijn keuzes.

In code:

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'),
      ),
    );
  }
}
De vraag is gesteld op 09/10/2019 om 12:58
bron van user
In andere talen...                            

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