BottomNavigationBar ne montre pas l'onglet en cours lorsque vous utilisez le widget offStageNavigator

voix
0

Je suis en train de construire un bottomNavigationBaroù chaque TabItem maintiendra son propre état de navigation.

J'ai 5 nav articles: enum TabItem { top_stories, topics, special_reports, more }. Pour la 1ère J'utilise le HomeScreenwidget pour afficher la liste des articles. Chaque article peut être cliqué pour afficher tout son contenu. Pour la 2ème TabItem (sujets), je voudrais afficher une autre liste d'éléments , mais pour l' instant j'utilise le TopicScreenwidget pour afficher d' un simple Textchamp.

Dans mon NewsApp, je me sers d' un Stacket un Offstagewidget de autour de ma Navigatorclasse pour chacun des TabItems.

Pour la 1ère tabItemtout fonctionne OK. Lorsque je clique sur topicsbien, je ne vois pas le contenu respectif un TopicScreenwidget , mais la liste complète des articles apparaît à nouveau. La chose étrange est que cette liste semble être créée à partir de zéro pour cette TabItem. Je peux parfaitement choisir un autre article pour chaque TabItem, naviguer à travers toutes les bottomNavOptions et l'application va « se souvenir » mes choix.

Dans du 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'),
      ),
    );
  }
}
Créé 09/10/2019 à 12:58
source utilisateur
Dans d'autres langues...                            

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