1

I have this:

class PageService {
  static int CurrentPage = 0;
}

And I have this:

import 'package:flutter/material.dart';

import '../services/page_service.dart';

class NavigationMenu extends StatefulWidget {
  const NavigationMenu({super.key});

  @override
  State<NavigationMenu> createState() => _NavigationMenuState();
}

class _NavigationMenuState extends State<NavigationMenu> {
  @override
  Widget build(BuildContext context) {
    return NavigationBar(
      destinations: const [
        NavigationDestination(
            icon: Icon(
              Icons.home,
              color: Colors.white,
            ),
            label: "Home"),
        NavigationDestination(icon: Icon(Icons.forum), label: "Forums"),
      ],
      backgroundColor: const Color.fromARGB(255, 154, 15, 5),
      onDestinationSelected: (int index) {
        setState(() {
          PageService.CurrentPage = index;
          int test = PageService.CurrentPage;
          print("SETTING $test");
        });
      },
      selectedIndex: PageService.CurrentPage,
    );
  }
}

Then in my main, I have this:

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'BeastBurst',
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You'll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or simply save your changes to "hot reload" in a Flutter IDE).
        // Notice that the counter didn't reset back to zero; the application
        // is not restarted.
        primarySwatch: Colors.red,
      ),
      home: const BeastBurst(title: 'BeastBurst'),
    );
  }
}

class BeastBurst extends StatefulWidget {
  const BeastBurst({super.key, required this.title});

  // This widget is the home page of your application. It is stateful, meaning
  // that it has a State object (defined below) that contains fields that affect
  // how it looks.

  // This class is the configuration for the state. It holds the values (in this
  // case the title) provided by the parent (in this case the App widget) and
  // used by the build method of the State. Fields in a Widget subclass are
  // always marked "final".

  final String title;

  @override
  State<BeastBurst> createState() => _BeastBurstState();
}

class _BeastBurstState extends State<BeastBurst> {
  int _counter = 0;
  bool _loggedIn = false;

  List<Widget> pages = const [HomePage(), Forums()];

  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return Scaffold(
      body: pages[PageService.CurrentPage],
      // This trailing comma makes auto-formatting nicer for build methods.
    );
  }
}

When I navigate over the navigation menu I see the output of print like:

SETTING 1
SETTING 0
SETTING 1
SETTING 1

However, page switching does not happen unless I press CRTL+S on the VSCode editor. Looks like it reads the value of PageService.CurrentPage only on the editor save.

This issue happened once I made PageService.CurrentPage static. Any idea why is that and how can I fix it?

1
  • Can you include more about main widget Commented Nov 15, 2022 at 16:19

2 Answers 2

1

Actually here, in your NavigationMenu class you're updating the state of the class and not it's parent class, in which you're using the NavigationMenu, which is why the state of the parent class isn't' changed and the build method isn't recalled and the updated value of PageService.CurrentIndex isn't referenced again.

In the class where you have used the NavigationMenu:

@override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(),
      bottomNavigationBar: NavigationMenu(
        onDestinationSelected: (index) {
          setState(() {
            PageService.CurrentPage = index;
            int test = PageService.CurrentPage;
            print("SETTING $test");
          });
        },
      ),
      body: pages[PageService.CurrentPage],
    );
  }

Updated NavigationMenu class:

class NavigationMenu extends StatefulWidget {
  final Function(int) onDestinationSelected;
  const NavigationMenu({super.key, required this.onDestinationSelected});

  @override
  State<NavigationMenu> createState() => _NavigationMenuState();
}

class _NavigationMenuState extends State<NavigationMenu> {
  @override
  Widget build(BuildContext context) {
    return NavigationBar(
      destinations: const [
        NavigationDestination(
            icon: Icon(
              Icons.home,
              color: Colors.white,
            ),
            label: "Home"),
        NavigationDestination(icon: Icon(Icons.forum), label: "Forums"),
      ],
      backgroundColor: const Color.fromARGB(255, 154, 15, 5),
      onDestinationSelected: widget.onDestinationSelected,
      selectedIndex: PageService.CurrentPage,
    );
  }
}

Alternate solution:

In your NavigationMenu class, change:

onDestinationSelected: (int index) {
    setState(() {
      PageService.CurrentPage = index;
      int test = PageService.CurrentPage;
      print("SETTING $test");
    });
  }

to:

onDestinationSelected: (int index) {
  final parentState = context.findAncestorStateOfType<_MyHomePageState>();
  
  parentState?.setState(() {
    PageService.CurrentPage = index;
    int test = PageService.CurrentPage;
    print("SETTING $test");
  });
}

Note: Change _MyHomePageState to your class state in which you're using the NavigationMenu.

Sign up to request clarification or add additional context in comments.

6 Comments

Hey NavigationMenu is used over several classes, not just one.
@Venelin, I have updated my answer, used callback function to setstate in the class where the NavigationMenu is used.
Tried both ways none work. See the updated question I've added info there about the main class.
Worked I had t reload fully.
@Venelin, I don't see that you followed my answer. You have set the callback in the NavigationMenu class but I did something else .Check the answer.
|
0

You need to make main widget as StatefulWidget while will update the UI here too. I am using a callback method instead of global variable.

class NavigationMenu extends StatefulWidget {
  const NavigationMenu({super.key, required this.selected});

  final Function(int) selected;
//....
      onDestinationSelected: (int index) {
        widget.selected(index);//update parent callback
        setState(() {});
      },
      selectedIndex: PageService.CurrentPage,
    );
  }

And use case

class _ExampleScreenState extends State<ExampleScreen> {
  int activeIndex = 0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        bottomNavigationBar: NavigationMenu(
          selected: (p0) {
            //PageService.CurrentPage=0;
              activeIndex = p0;
             setState(() {});
          },
        ),
        body: [Text("a"), Text("B")][activeIndex] //PageService.CurrentPage

4 Comments

Hello I've added more to the question.
Does my snippet fail?
The snippet is really broad and it seems not addressing the static variable issue I am experiencing :(
yap, global variable isnt needed here. just track the final Function(int) selected; you will get it

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.