Search code examples
flutterdartflutter-layoutflutter-state

Flutter setstate method doesn't add my numbers


I built custom app for training. I created buttons with gesture detector and i assigned number to them and i created global variable "score". I want buttons to add their numbers to "score" variable and i want to show the variable in a container but Somehow it does not work.Can it be about states?Does anyone help me?


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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        appBarTheme: const AppBarTheme(
          backgroundColor: Colors.deepPurple,
          centerTitle: true,
          elevation: 3,
        ),
      ),
      home: const HomeScreen(),
    );
  }
}

class HomeScreen extends StatelessWidget {
  const HomeScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text("My Application"),
      ),
      body: const Body(),
    );
  }
}

int score = 5;

class Body extends StatefulWidget {
  const Body({Key? key}) : super(key: key);

  @override
  State<Body> createState() => _BodyState();
}

class _BodyState extends State<Body> {
  @override
  Widget build(BuildContext context) {
    return Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Container(
          height: 50,
          width: 200,
          decoration: const BoxDecoration(color: Colors.grey),
          child: Center(child: Text(score.toString())),
        ),
        const SizedBox(
          height: 70,
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
            Numb(
              color: Colors.pink,
              numb: 1,
            ),
            Numb(
              color: Colors.pink,
              numb: 2,
            ),
            Numb(
              color: Colors.pink,
              numb: 3,
            ),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
            Numb(
              color: Colors.pink,
              numb: 4,
            ),
            Numb(
              color: Colors.pink,
              numb: 5,
            ),
            Numb(
              color: Colors.pink,
              numb: 6,
            ),
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.center,
          children: const [
            Numb(
              color: Colors.pink,
              numb: 7,
            ),
            Numb(
              color: Colors.pink,
              numb: 8,
            ),
            Numb(
              color: Colors.pink,
              numb: 9,
            ),
          ],
        ),
      ],
    );
  }
}

class Numb extends StatefulWidget {
  final int? numb;
  final Color? color;

  const Numb({
    Key? key,
    required this.numb,
    required this.color,
  }) : super(key: key);

  @override
  State<Numb> createState() => _NumbState();
}

class _NumbState extends State<Numb> {
  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        setState(() {
          score += widget.numb!;
        });
      },
      child: Container(
        margin: projectPadding.allPad * 0.5,
        decoration: BoxDecoration(color: widget.color),
        height: MediaQuery.of(context).size.height * 0.06,
        width: MediaQuery.of(context).size.width * 0.1,
        child: Center(
          child: Text(widget.numb.toString()),
        ),
      ),
    );
  }
}

class projectPadding {
  static const EdgeInsets horizantalPad = EdgeInsets.symmetric(horizontal: 20);
  static const EdgeInsets verticalPad = EdgeInsets.symmetric(vertical: 20);
  static const EdgeInsets allPad = EdgeInsets.all(20);
}

Solution

  • Numb setState only update the _NumbState ui. in order to update parent widget, you can use callback method that will trigger setState on parent UI.

    class Numb extends StatefulWidget {
      final int? numb;
      final Color? color;
    
      final Function(int) callBack;
    
      const Numb({
        Key? key,
        required this.numb,
        required this.color,
        required this.callBack,
      }) : super(key: key);
    
      @override
      State<Numb> createState() => _NumbState();
    }
    
    
    ///....
    
    onTap: () {
        setState(() {
          score += widget.numb!;
        });
        widget.callBack(score);
      },
    

    And you can add logic and others operation like

    Numb(
      color: Colors.pink,
      numb: 1,
      callBack: (p0) {
        setState(() {});
      },
    ),
    

    I will also recommend starting state-management like riverpod / bloc