Shared BottomNavigationBar не обновляется на главном экране - PullRequest
0 голосов
/ 02 августа 2020
• 1000 * Использование предоставленной BottomNavigationBar там, где это необходимо (в данном случае ProductScreen)

Но проблема в том, что когда я перехожу со страницы Page1 -> ProductScreen (щелкните контейнер «Go to Products» из PageOne) и обратно в ProductScreen -> Page2 (щелкните второй элемент в BottomNavigationBar), BottomNavigationBar не обновляется. Однако представление стека обновляется (отображает PageTwo). Не могли бы вы помочь мне понять, почему панель навигации не обновляется. Заранее спасибо.

Для этого я сохранил все классы в main.dart, как показано ниже.

import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

void main() {
  runApp(MultiProvider(
    providers: [
      ChangeNotifierProvider(
        create: (_) => NavBar(),
      ),
    ],
    child: MyApp(),
  ));
}

// navigation bar
class NavBar extends StatefulWidget with ChangeNotifier {
  Function callBack;
  int selectedIndex = 0;

  NavBar({
    this.callBack,
  });

  void setCallBack(Function callBack) {
    this.callBack = callBack;
  }

  void setIndex(index) {
    selectedIndex = index;
    notifyListeners();
  }

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

class _NavBarState extends State<NavBar> {
  void _onNavItemClicked(index) {
    Navigator.of(context).popUntil(ModalRoute.withName('/'));

    print("${widget.selectedIndex} => $index");
    setState(() {
      widget.setIndex(index);
    });
    widget.callBack(index);
  }

  @override
  Widget build(BuildContext context) {
    return BottomNavigationBar(
      currentIndex: widget.selectedIndex,
      selectedItemColor: Colors.blue,
      onTap: _onNavItemClicked,
      type: BottomNavigationBarType.fixed,
      items: [
        BottomNavigationBarItem(
          icon: Icon(Icons.shopping_cart),
          title: Text("One"),
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.border_color),
          title: Text("Two"),
        ),
        BottomNavigationBarItem(
          icon: Icon(Icons.account_circle),
          title: Text("Three"),
        ),
      ],
    );
  }
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: HomeScreen(),
      routes: {
        ProductScreen.routeName: (context) => ProductScreen(),
      },
    );
  }
}

class HomeScreen extends StatefulWidget {
  HomeScreen();

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

class _HomeScreenState extends State<HomeScreen> {
  int _stackIndex = 0;
  NavBar navBar;

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

  void _changeStackIndex(int index) {
    setState(() {
      _stackIndex = index;
    });
  }

  @override
  Widget build(BuildContext context) {
    print("Homescreen rebuilding...");

    navBar = Provider.of<NavBar>(context);
    navBar.setCallBack(_changeStackIndex);

    return Scaffold(
      appBar: AppBar(
        title: Text("Project Title"),
        centerTitle: true,
      ),
      bottomNavigationBar: navBar,
      body: Center(
        child: IndexedStack(
          index: _stackIndex,
          children: <Widget>[
            PageOne(),
            PageTwo(),
            PageThree(),
          ],
        ),
      ),
    );
  }
}

class PageOne extends StatefulWidget {
  @override
  _PageOneState createState() => _PageOneState();
}

class _PageOneState extends State<PageOne> {
  List<int> intList = List.generate(20, (index) => index);

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          GotoProductsLink(),
          ListView.builder(
            physics: ScrollPhysics(),
            itemCount: 20,
            shrinkWrap: true,
            itemBuilder: (context, index) =>
                SingleContainer("One: " + intList[index].toString()),
          ),
        ],
      ),
    );
  }
}

class PageTwo extends StatefulWidget {
  @override
  _PageTwoState createState() => _PageTwoState();
}

class _PageTwoState extends State<PageTwo> {
  List<int> intList = List.generate(20, (index) => index);

  @override
  Widget build(BuildContext context) {
    return SingleChildScrollView(
      child: Column(
        children: <Widget>[
          GotoProductsLink(),
          ListView.builder(
            physics: ScrollPhysics(),
            itemCount: 20,
            shrinkWrap: true,
            itemBuilder: (context, index) =>
                SingleContainer("Two: " + intList[index].toString()),
          ),
        ],
      ),
    );
  }
}

class PageThree extends StatefulWidget {
  @override
  _PageThreeState createState() => _PageThreeState();
}

class _PageThreeState extends State<PageThree> {
  List<int> intList = List.generate(20, (index) => index);

  @override
  Widget build(BuildContext context) {
    return ListView.builder(
      itemCount: 20,
      shrinkWrap: true,
      itemBuilder: (context, index) =>
          SingleContainer("Three: " + intList[index].toString()),
    );
  }
}

class GotoProductsLink extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        Navigator.of(context).pushNamed(ProductScreen.routeName);
      },
      child: Container(
        alignment: Alignment.center,
        color: Colors.blue,
        width: double.infinity,
        padding: EdgeInsets.all(20),
        child: Text(
          "Go to Products",
          style: TextStyle(
            color: Colors.white,
            fontWeight: FontWeight.bold,
          ),
        ),
      ),
    );
  }
}

class SingleContainer extends StatelessWidget {
  String text;

  SingleContainer(this.text);

  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.grey.withOpacity(0.1),
      height: 100,
      padding: EdgeInsets.all(30),
      margin: EdgeInsets.only(bottom: 10),
      child: Center(
        child: Text(text),
      ),
    );
  }
}

////////////////////////////////////////
// this screen can be invoked from multiple pages
class ProductScreen extends StatefulWidget {
  static String routeName = "/products";

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

class _ProductScreenState extends State<ProductScreen> {
  List<int> gridItems = List.generate(20, (index) => index);

  @override
  Widget build(BuildContext context) {
    NavBar navBar = Provider.of<NavBar>(context);
    return Scaffold(
      appBar: AppBar(),
      bottomNavigationBar: navBar,
      body: GridView.builder(
        itemCount: 20,
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 2,
          crossAxisSpacing: 5,
          mainAxisSpacing: 5,
        ),
        itemBuilder: (context, index) => Container(
          color: Colors.blue.withOpacity(0.1),
          child: Center(
            child: Text("Single Product"),
          ),
        ),
      ),
    );
  }
}
...