持久的底部导航栏,但仅在某些页面中

时间:2021-05-18 22:18:39

标签: android flutter dart flutter-bottomnavigation

我在 HomePage 中有以下代码(我将在下面展示)将它从文章中取出,它是一个堆栈,我在底部导航栏中有 5 个页面,

enter image description here

我想要做的是,从 HomeView 中,当触摸容器 _publicity() 方法时,会打开一个“公开”屏幕,该屏幕必须保持底部导航栏打开良好并且底部导航栏仍然存在(图片1) .但是,当我从另一个容器 _promotions() 方法转到一个外部页面时,该页面不包含底部导航栏,例如 Navigator.Push,这会打开页面,但带有底部导航栏!和上面的首页AppBar,看起来应该是完全独立的脚手架/页面,似乎并没有离开首页脚手架(图2)。

(忽略这 2 个 AppBar,将被修复)

图像 1:

enter image description here

图像 2:

enter image description here

是的,我希望BottomNavigationBar 保持不变,但是当我尝试导航到另一个不需要BottomNavigationBar 的独立外部页面时,它会像我说的那样显示在HOMEPAGE 内,这是错误的,因为它应该是一个完全独立的脚手架,处理这个花了几天时间,我找不到解决方案!!!

关于该代码的另一个问题,正如我所说的代码部分是堆栈,TabNavigator 将其从文章中取出,这是一种好的做法吗?因为我是初学者,我想了解更多。

主页:

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

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

class _HomePageState extends State<HomePage> {
  PageController _pageController;

  Future<EmpresaModel> empresaFuture;

  Future<EmpresaModel> _getEmpresa = TestService().getEmpresa();

  @override
  void initState() {
    super.initState();
    _pageController = PageController();
    empresaFuture = _getEmpresa;
  }

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

  Directory libCacheDir = Directory("");
  final double dividerIndent = 10;
  int currentButton = 0;

  String _currentPage = "Page1";
  List<String> pageKeys = ["Page1", "Page2", "Page3", "Page4", "Page5"];
  Map<String, GlobalKey<NavigatorState>> _navigatorKeys = {
    "Page1": GlobalKey<NavigatorState>(),
    "Page2": GlobalKey<NavigatorState>(),
    "Page3": GlobalKey<NavigatorState>(),
    "Page4": GlobalKey<NavigatorState>(),
    "Page5": GlobalKey<NavigatorState>(),
  };

  void _selectTab(String tabItem, int index) {
    if (tabItem == _currentPage) {
      _navigatorKeys[tabItem].currentState.popUntil((route) => route.isFirst);
    } else {
      setState(() {
        _currentPage = pageKeys[index];
        currentButton = index;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        final isFirstRouteInCurrentTab =
            !await _navigatorKeys[_currentPage].currentState.maybePop();
        if (isFirstRouteInCurrentTab) {
          if (_currentPage != "Page1") {
            _selectTab("Page1", 1);

            return false;
          }
        }
        return isFirstRouteInCurrentTab;
      },
      child: SafeArea(
          child: GestureDetector(
              onTap: () async {
                FocusScopeNode currentFocus = FocusScope.of(context);
                currentFocus.unfocus();
              },
              child: Scaffold(
                appBar: (currentButton == 4) ? SettingsAppBar() : CustomAppBar(),
                body: FutureBuilder(
                    future: empresaFuture,
                    builder: (BuildContext context,
                        AsyncSnapshot<EmpresaModel> snapshot) {
                      if (snapshot.connectionState == ConnectionState.waiting) {
                        return Center(child: CircularProgressIndicator());
                      } else if (snapshot.hasError) {
                        return Column(
                          mainAxisAlignment: MainAxisAlignment.center,
                          crossAxisAlignment: CrossAxisAlignment.center,
                          children: [
                            const Icon(
                              Icons.error_outline,
                              color: Colors.red,
                              size: 60,
                            ),
                            Center(
                              child: Text('Error: ${snapshot.error}'),
                            )
                          ],
                        );
                      } else {
                        return SizedBox.expand(
                          child: Stack(
                            children: [
                              _buildOffstageNavigator(
                                "Page1",
                                snapshot.data.links,
                                snapshot.data.publi,
                              ),
                              _buildOffstageNavigator("Page2"),
                              _buildOffstageNavigator("Page3"),
                              _buildOffstageNavigator("Page4"),
                              _buildOffstageNavigator("Page5"),
                            ],
                          ),
                        );
                      }
                    }),
                // views[currentButton],

                bottomNavigationBar: BottomNavigationBar(
                  selectedItemColor: Colors.black,
                  type: BottomNavigationBarType.fixed,
                  currentIndex: currentButton,
                  onTap: (int index) {
                    _selectTab(pageKeys[index], index);
                  },
                  //_onItemTapped,
                  items: [
                    BottomNavigationBarItem(
                        icon: Icon(Icons.home_filled),
                        label: S.of(context).homePageBottomBarHome),
                    BottomNavigationBarItem(
                        icon: Icon(Icons.local_mall),
                        label: S.of(context).homePageBottomBarBuy),
                    BottomNavigationBarItem(
                        icon: Icon(Icons.storefront),
                        label: S.of(context).homePageBottomBarTradeMark),
                    BottomNavigationBarItem(
                        icon: Icon(Icons.shopping_cart),
                        label: S.of(context).homePageBottomBarCart),
                    BottomNavigationBarItem(
                        icon: Icon(Icons.person),
                        label: S.of(context).homePageBottomBarProfile),
                  ],
                ),
              ))),
    );
  }

  Widget _buildOffstageNavigator(
    String tabItem, [
    List<Link> listLink,
    List<Publi> listPubli,
  ]) {
    return Offstage(
      offstage: _currentPage != tabItem,
      child: TabNavigator(
        navigatorKey: _navigatorKeys[tabItem],
        tabItem: tabItem,
        listLink: listLink,
        listPubli: listPubli,
      ),
    );
  }

}

家庭视图:

class HomeView extends StatefulWidget {
  final listLink;
  final listPubli;

  const HomeView({
    Key key,
    this.listLink,
    this.listPubli,
  }) : super(key: key);

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

class _HomeViewState extends State<HomeView> {
  final double dividerIndent = 10;

  @override
  Widget build(BuildContext context) {
    final size = MediaQuery.of(context).size;
    return Scaffold(
      body: SingleChildScrollView(
        child: Column(
          children: <Widget>[
            _searchBar(),
            SizedBox(height: 5),
            CategoryList(
              listLinkCategorias: widget.listLink,
            ),
            SizedBox(height: size.height * 0.03),
            _promotions(size),
            SizedBox(height: size.height * 0.025),
            _publicity(widget.listPubli),
            SizedBox(height: size.height * 0.03),
            _pageViewProducts(),
            SizedBox(height: 50),
          ],
        ),
      ),
    );
  }

  _searchBar() {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 0, vertical: 15),
      height: 60,
      width: double.infinity,
      child: FloatingSearchBar(
        elevation: 1,
        backdropColor: Colors.transparent,
        backgroundColor: Colors.grey[200],
        hint: S.of(context).homePageSearchBar,
        scrollPadding: const EdgeInsets.only(top: 16, bottom: 56),
        transitionDuration: const Duration(milliseconds: 800),
        transitionCurve: Curves.easeInOut,
        physics: const BouncingScrollPhysics(),
        openAxisAlignment: 0.0,
        debounceDelay: const Duration(milliseconds: 500),
        onQueryChanged: (query) {
          // Call your model, bloc, controller here.
        },
        // Specify a custom transition to be used for
        // animating between opened and closed stated.
        transition: CircularFloatingSearchBarTransition(),
        actions: [
          FloatingSearchBarAction.searchToClear(
            showIfClosed: true,
          ),
        ],
        builder: (context, transition) {
          return ClipRRect(
            borderRadius: BorderRadius.circular(8),
            child: Material(
              color: Colors.white,
              elevation: 0,
              child: Column(
                mainAxisSize: MainAxisSize.min,
                children: Colors.accents.map((color) {
                  return Container(height: 112, color: color);
                }).toList(),
              ),
            ),
          );
        },
      ),
    );
  }

  Widget _promotions(size) {
    return GestureDetector(
      onTap: () {
        Navigator.push(
            context,
            new MaterialPageRoute(
                builder: (BuildContext context) => new ProductosPage()));
      },
      child: Container(
        height: size.height * 0.34,
        width: double.infinity,
        margin: EdgeInsets.symmetric(horizontal: 8.0),
        child: ClipRRect(
          borderRadius: BorderRadius.only(
              topLeft: Radius.circular(10), topRight: Radius.circular(10)),
          child: Image.asset(
            'assets/images/promociones.jpg',
            fit: BoxFit.cover,
          ),
        ),
      ),
    );
  }

  Widget _publicity(List<Publi> listPubli) {
    // final _pagesBloc = BlocProvider.of<PagesBloc>(context);
    return GestureDetector(
      onTap: () {
        // _pagesBloc.add(PagesEvents.publicityView);
        Navigator.push(
            context,
            new MaterialPageRoute(
                builder: (BuildContext context) => new PublicityPage()));

      },
      child: Container(
        alignment: Alignment.center,
        margin: EdgeInsets.symmetric(horizontal: 8.0),
        height: 86,
        width: double.infinity,
        decoration: BoxDecoration(
            borderRadius: BorderRadius.circular(10), color: Colors.grey[300]
            ),
        child: CachedNetworkImage(
          imageUrl: TestService().baseURL + listPubli[0].img,
          fit: BoxFit.contain,
          errorWidget: (context, url, error) => Icon(Icons.error),
        ),
      ),
    );
  }

  Widget _pageViewProducts() {
    return Container(
      height: 250,
      width: double.infinity,
      child: ListView.separated(
          physics: PageScrollPhysics(),
          separatorBuilder: (context, index) => Divider(
                indent: dividerIndent,
              ),
          scrollDirection: Axis.horizontal,
          controller: PageController(viewportFraction: 0.5, initialPage: 0),
          itemCount: products.length,
          itemBuilder: (context, index) {
            if (index == 0) {
              return Padding(
                child: _productSelector(index),
                padding: EdgeInsets.only(left: dividerIndent),
              );
            } else if (index == products.length - 1) {
              return Padding(
                child: _productSelector(index),
                padding: EdgeInsets.only(right: dividerIndent),
              );
            }
            return _productSelector(index);
          }),
    );
  }

  Widget _productSelector(int index) {
    return Container(
      height: 250,
      width: 150,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Container(
            width: 150,
            padding: EdgeInsets.all(14),
            decoration: BoxDecoration(color: Colors.grey.shade300),
            child: Stack(
              children: <Widget>[
                Container(
                  height: 160,
                  width: 130,
                  child: Center(
                    child: Image.asset(
                      products[index].imagename,
                      fit: BoxFit.contain,
                    ),
                  ),
                ),
                Positioned(
                  bottom: 0,
                  right: 0,
                  child: Container(
                    padding: EdgeInsets.all(10),
                    decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(6),
                        color: Colors.black),
                    child: Icon(
                      Icons.add,
                      color: Colors.white,
                      size: 15,
                    ),
                  ),
                ),
              ],
            ),
          ),
          Container(
            margin: EdgeInsets.only(left: 5),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text('${products[index].name}',
                    style: TextStyle(
                        fontSize: 12.8,
                        fontWeight: FontWeight.w500,
                        color: Colors.grey[600]),
                    overflow: TextOverflow.ellipsis),
                Text('\$${products[index].price}',
                    style: TextStyle(fontSize: 13, fontWeight: FontWeight.w600),
                    overflow: TextOverflow.ellipsis),
              ],
            ),
          ),
        ],
      ),
    );
  }
}

标签导航器:

class TabNavigatorRoutes {
  static const String root = '/';
  static const String detail = '/detail';
}

class TabNavigator extends StatelessWidget {
  TabNavigator({this.navigatorKey, this.tabItem, this.listLink, this.listPubli});
  final GlobalKey<NavigatorState> navigatorKey;
  final String tabItem;
  final listLink;
  final listPubli;

  @override
  Widget build(BuildContext context) {

    Widget child ;
    if(tabItem == "Page1")
      child = HomeView(listLink: listLink, listPubli: listPubli);
    else if(tabItem == "Page2")
      child = BuyView();
    else if(tabItem == "Page3")
      child = BrandView();
    else if(tabItem == "Page4")
      child = CartView();
    else if(tabItem == "Page5")
      child = SettingsView();
    
    return Navigator(
      key: navigatorKey,
      onGenerateRoute: (routeSettings) {
        return MaterialPageRoute(
          builder: (context) => child
        );
      },
    );
  }
}

0 个答案:

没有答案