Home > Enterprise >  onTap, setState, optimisation
onTap, setState, optimisation

Time:11-18

I have created an app with multiple buttons with some adjusting counters and others adjusting bools. (for widget visibility) these buttons have been prebuilt in stateless their own dart file that I can then call on. the problem I'm having is all my setState functions are very similar but with only slight changes. which is making my code very long. Is there a way to tidy this up and have the ontap in the stateless widgets and the setstates in a seperate dart file I can then call on?

here is my main page:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'test2.dart';

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

  @override
  State<TestMain> createState() => _TestMainState();
}

class _TestMainState extends State<TestMain> {
  int localCounter1 = 0;
  int localCounter2 = 0;
  int globalCounter = 0;
  bool bool1 = false;
  bool bool2 = false;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.black,
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          CounterAndButtons(
            minusButton: InkWell(
              onTap: () {
                setState(() {
                  if (localCounter1 <= 0) return;
                  if (localCounter1 > 0) localCounter1--;
                  if (globalCounter > 0) globalCounter--;
                });
              },
              child: PlusMinusButton(
                  icon: CupertinoIcons.minus,
                  bgColor: Colors.blueGrey,
                  iconColor: Colors.white),
            ),
            counter: Counter(counter: '$localCounter1'),
            plusButton: InkWell(
              onTap: () {
                setState(() {
                  if (globalCounter >= 12) return;
                  if (localCounter1 < 12) localCounter1  ;
                  if (globalCounter < 12) globalCounter  ;
                });
              },
              child: PlusMinusButton(
                  icon: CupertinoIcons.plus,
                  bgColor: Colors.blueGrey,
                  iconColor: Colors.white),
            ),
          ),
          SizedBox(
            height: 20,
          ),
          CounterAndButtons(
            minusButton: InkWell(
              onTap: () {
                setState(() {
                  if (localCounter2 <= 0) return;
                  if (localCounter2 > 0) localCounter2--;
                  if (globalCounter > 0) globalCounter--;
                });
              },
              child: PlusMinusButton(
                  icon: CupertinoIcons.minus,
                  bgColor: Colors.blueGrey,
                  iconColor: Colors.white),
            ),
            counter: Counter(counter: '$localCounter2'),
            plusButton: InkWell(
              onTap: () {
                setState(() {
                  if (globalCounter >= 12) return;
                  if (localCounter2 < 12) localCounter2  ;
                  if (globalCounter < 12) globalCounter  ;
                });
              },
              child: PlusMinusButton(
                  icon: CupertinoIcons.plus,
                  bgColor: Colors.blueGrey,
                  iconColor: Colors.white),
            ),
          ),
          SizedBox(
            height: 20,
          ),
          Counter(counter: '$globalCounter'),
          SizedBox(
            height: 20,
          ),
          InkWell(
            onTap: () {
              setState(() {
                bool1 = true;
                bool2 = true;
              });
            },
            child: NormalButtons(
                tpNumber: 'button Text',
                boxColor: Colors.blueGrey,
                textColor: Colors.white),
          ),
        ],
      ),
    );
  }
}

and here is my stateless class widgets that i call on:

import 'package:flutter/material.dart';

class PlusMinusButton extends StatelessWidget {
  PlusMinusButton(
      {required this.icon, required this.bgColor, required this.iconColor});

  final Color bgColor;
  final Color iconColor;
  final IconData icon;

  @override
  Widget build(BuildContext context) {
    return Container(
      constraints: BoxConstraints(
        minWidth: 30,
        maxWidth: 80,
        minHeight: 80,
        maxHeight: 80,
      ),
      margin: EdgeInsets.all(9),
      decoration: BoxDecoration(
        color: bgColor,
        borderRadius: BorderRadius.circular(10),
      ),
      child: FittedBox(
        fit: BoxFit.scaleDown,
        child: Icon(
          icon,
          color: iconColor,
        ),
      ),
    );
  }
}

class CounterAndButtons extends StatelessWidget {
  CounterAndButtons(
      {required this.minusButton,
      required this.counter,
      required this.plusButton});

  final Widget minusButton;
  final Widget counter;
  final Widget plusButton;
  @override
  Widget build(BuildContext context) {
    return Row(
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        minusButton,
        counter,
        plusButton,
      ],
    );
  }
}

class Counter extends StatelessWidget {
  Counter({required this.counter});

  final String counter;
  @override
  Widget build(BuildContext context) {
    return Text(
      counter,
      style: TextStyle(fontSize: 60),
      maxLines: 1,
    );
  }
}

class NormalButtons extends StatelessWidget {
  NormalButtons(
      {required this.tpNumber,
      required this.boxColor,
      required this.textColor});

  final String tpNumber;
  final Color boxColor;
  final Color textColor;

  @override
  Widget build(BuildContext context) {
    return Container(
      margin: EdgeInsets.symmetric(horizontal: 5, vertical: 8),
      padding: EdgeInsets.all(3),
      decoration: BoxDecoration(
        color: boxColor,
        borderRadius: BorderRadius.circular(10),
      ),
      child: Center(
        child: Text(
          tpNumber,
          style: TextStyle(color: textColor, fontSize: 80),
          textAlign: TextAlign.center,
          maxLines: 2,
        ),
      ),
    );
  }
}

CodePudding user response:

You can pass onTap as a parameter to your PlusMinusButton like this :

class PlusMinusButton extends StatelessWidget {
  PlusMinusButton({required this.icon, required this.bgColor, required this.iconColor, this.onTap});

  final Color bgColor;
  final Color iconColor;
  final IconData icon;
  final VoidCallback? onTap;

  @override
  Widget build(BuildContext context) {
    return InkWell(
      onTap: onTap,
      child: Container(
        constraints: BoxConstraints(
          minWidth: 30,
          maxWidth: 80,
          minHeight: 80,
          maxHeight: 80,
        ),
        margin: EdgeInsets.all(9),
        decoration: BoxDecoration(
          color: bgColor,
          borderRadius: BorderRadius.circular(10),
        ),
        child: FittedBox(
          fit: BoxFit.scaleDown,
          child: Icon(
            icon,
            color: iconColor,
          ),
        ),
      ),
    );
  }
}

In your main file :

PlusMinusButton(
                onTap: () {
                  setState(() {
                    if (localCounter1 <= 0) return;
                    if (localCounter1 > 0) localCounter1--;
                    if (globalCounter > 0) globalCounter--;
                  });
                },
                icon: CupertinoIcons.minus,
                bgColor: Colors.blueGrey,
                iconColor: Colors.white)
  • Related