Flutter: значение свойства currentIndex в BottomNavigationBar не обновляется при обновлении состояния - PullRequest
0 голосов
/ 15 апреля 2020

У меня есть BottomNavigationBar, которая перемещается на другие страницы при нажатии значка. Это работает нормально, за исключением того, что значение свойства currentIndex в BottomNavigationBar не обновляется при обновлении состояния, что означает отсутствие изменений в текущем BottomNavigationBar. введите описание изображения здесь

Я использую переменную (_selectedPage) для отслеживания выбранного индекса в BottomNavigationBar, и значение изменяется при касании элемента, но оно не обновляет свойство currentIndex при обновлении состояния .. почему это так?

import 'package:flutter/material.dart';
import 'package:independentproject/pages/home_page.dart';
import 'package:independentproject/pages/cook_recipe.dart';

class PageNavigationBar extends StatefulWidget {
  @override
  _PageNavigationBarState createState() => _PageNavigationBarState();
}

class _PageNavigationBarState extends State<PageNavigationBar> {
  //default page showing in bottom navigation bar will be CookRecipe()
  int _selectedPage = 1;

//all pages optional in bottom navigation bar
  final List<Widget> _pageOptions = [
    HomePage(),
    CookRecipe(),
  ];

  void onTapped(int pageTapped) {
    setState(() {
      //print(pageTapped);
      _selectedPage = pageTapped;
      Navigator.push(context, MaterialPageRoute(builder: (context) => _pageOptions[pageTapped]));
      //print(_selectedPage);
    });
  }

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      //TODO: currentIndex: doesn't update when the state updates, why?
      currentIndex: _selectedPage,
        //items showing in bottom navigation bar
      items: [
        BottomNavigationBarItem(
          icon: Icon(Icons.home),
          title: Text('Homepage'),
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.search),
          title: Text('Search recipe'),
        ),
      ],
      onTap: (int pageTapped) {
        onTapped(pageTapped);
      },
    );
  }
}

import 'package:flutter/material.dart';
import 'package:independentproject/page_navigation_bar.dart';

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Home page'),
        ),
        body: Center(
          child: Text('Home page'),
        ),
        bottomNavigationBar: PageNavigationBar(),
      ),
    );
  }
}

import 'package:flutter/material.dart';
import 'package:independentproject/page_navigation_bar.dart';

class CookRecipe extends StatefulWidget {
  @override
  _CookRecipeState createState() => _CookRecipeState();
}

class _CookRecipeState extends State<CookRecipe> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Search recipe'),
        ),
        body: Center(
          child: Text('Search recipes'),
        ),
        bottomNavigationBar: PageNavigationBar(),
      ),
    );
  }
}

Ответы [ 3 ]

0 голосов
/ 15 апреля 2020

это потому, что PageNavigationBar - это собственный класс, когда вы называете setstate только обновления этого класса

взгляните на Provider очень полезный пакет управления состоянием

или вы также можете обрабатывать свою страницу, когда NavBar является вашим Main Page и у вас есть только одна страница

return MaterialApp(
  home: Scaffold(
      appBar: ownAppBar(_selectedPage),
      body: _bodyOptions[_selectedPage],
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _selectedPage,
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('Homepage'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            title: Text('Search recipe'),
          ),
        ],
        onTap: (int pageTapped) {
          onTapped(pageTapped);
        },
      )
  ),
);



final List<Widget> _bodyOptions = [
    HomePage(),
    CookRecipe(),
  ];
0 голосов
/ 15 апреля 2020

Вам не нужно использовать Навигатор для смены страниц, я изменил ваш код, просто попробуйте.

import 'package:flutter/material.dart';

main() {
  runApp(MaterialApp(home: PageNavigationBar()));
}

class PageNavigationBar extends StatefulWidget {
  @override
  _PageNavigationBarState createState() => _PageNavigationBarState();
}

class _PageNavigationBarState extends State<PageNavigationBar> {
  //default page showing in bottom navigation bar will be CookRecipe()
  int _selectedPage = 1;

//all pages optional in bottom navigation bar
  final List<Widget> _pageOptions = [
    HomePage(),
    CookRecipe(),
  ];

  void onTapped(int pageTapped) {
    setState(() {
      //print(pageTapped);
      _selectedPage = pageTapped;
//      Navigator.push(context, MaterialPageRoute(builder: (context) => _pageOptions[pageTapped]));
      //print(_selectedPage);
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _pageOptions[_selectedPage],
      bottomNavigationBar: BottomNavigationBar(
        //TODO: currentIndex: doesn't update when the state updates, why?
        currentIndex: _selectedPage,
        //items showing in bottom navigation bar
        items: [
          BottomNavigationBarItem(
            icon: Icon(Icons.home),
            title: Text('Homepage'),
          ),
          BottomNavigationBarItem(
            icon: Icon(Icons.search),
            title: Text('Search recipe'),
          ),
        ],
        onTap: (int pageTapped) {
          onTapped(pageTapped);
        },
      ),
    );
  }
}

class CookRecipe extends StatefulWidget {
  @override
  _CookRecipeState createState() => _CookRecipeState();
}

class _CookRecipeState extends State<CookRecipe> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Search recipes'),
    );
  }
}

class HomePage extends StatefulWidget {
  @override
  _HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Center(
      child: Text('Home page'),
    );
  }
}
0 голосов
/ 15 апреля 2020

Я бы посоветовал вам создать виджет, который будет содержать BottomNavigationBar, а также PageView, который позволит вам переключать страницы с помощью PageController. Например:

class _MainScreenState extends State<MainScreen> {
  PageController _pageController;
  int _page = 1;
  Duration pageChanging = Duration(milliseconds: 300);//this is for page animation-not necessary
  Curve animationCurve = Curves.linear;//this is for page animation-not necessary
  _MainScreenState();


@override
  void initState() {
    super.initState();
    _pageController = PageController(initialPage: 1);
  }


Widget build(BuildContext context) {
    return Scaffold(
      body: PageView(
        physics: BouncingScrollPhysics(),
        scrollDirection: Axis.horizontal,
        controller: _pageController,
        onPageChanged: onPageChanged,
        children: <Widget>[
          //here are all the pages you need:
          //CookRecipe(),
        ],
      ),
bottomNavigationBar: BottomNavigationBar(
          type: BottomNavigationBarType.fixed,
          items: <BottomNavigationBarItem>[
            BottomNavigationBarItem(
              icon: Icon(
                Icons.message,
              ),
              title: Container(height: 0.0),
            ),
            BottomNavigationBarItem(
              icon: Icon(
                Icons.home,
              ),
              title: Container(height: 0.0),
            ),
            BottomNavigationBarItem(
              icon: Icon(
                Icons.person,
              ),
              title: Container(height: 0.0),
            ),
          ],
          onTap: navigationTapped,
          selectedItemColor: Theme.of(context).backgroundColor,
          currentIndex: _page,
        ),
      ),
    );
  }

void navigationTapped(int page) {
    _pageController.animateToPage(page,duration: pageChanging,
      curve: animationCurve,);
  }



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

  void onPageChanged(int page) {
    if (this.mounted){
    setState(() {
      this._page = page;
    });
  }}


Вы также можете сделать это без PageView и использовать только контроллер для переключения страниц.

Кстати, вы создаете новый экземпляр панели навигации, когда вы загрузить страницу, которая является плохой практикой

...