2

If I change the value of the height by moving the slider, the values of the weight and age change back to their initial values. it should not be so, what am I doing wrong?

Initially, I thought the codes to the slider value and the weight and age values were connected, but I do not see any connection between them except for the style they use together; kLabelTextStyle and kNumberTextStyle

WeightAndAge.dart

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'constants.dart';

class ColumnWidgetForWeightAndAge extends StatefulWidget {
int number;
final String info;

ColumnWidgetForWeightAndAge({
this.number,
this.info,
});

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

class _ColumnWidgetForWeightAndAgeState
extends State<ColumnWidgetForWeightAndAge> {
@override
Widget build(BuildContext context) {
Widget minus = FloatingActionButton(
  onPressed: () {
    setState(() {
      if (widget.number > 0) {
        widget.number = widget.number - 1;
      }
    });
    print(widget.number);
  },
  backgroundColor: Color(0xFF4C4F5E),
  child: Icon(
    FontAwesomeIcons.minus,
    color: Colors.white,
  ),
);

Widget plus = FloatingActionButton(
  backgroundColor: Color(0xFF4C4F5E),
  onPressed: () {
    setState(() {
      if (widget.number > 0) {
        widget.number = widget.number + 1;
      }
    });
    print(widget.number);
  },
  child: Icon(
    FontAwesomeIcons.plus,
    color: Colors.white,
  ),
);

return Column(
  mainAxisAlignment: MainAxisAlignment.center,
  children: [
    Text(
      widget.info,
      style: kLabelTextStyle,
    ),
    Text(
      widget.number.toString(),
      style: kNumberTextStyle,
    ),
    Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        minus,
        SizedBox(
          width: 10,
        ),
        plus,
      ],
    )
  ],
);
}
}

input_page.dart

import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'icons.dart';
import 'containers.dart';
import 'constants.dart';
import 'weightAndAge.dart';

enum Gender { male, female }

class InputPage extends StatefulWidget {
 @override
 _InputPageState createState() => _InputPageState();
}

class _InputPageState extends State<InputPage> {
Gender selectedCardColor;
int height = 192;
int weight = 6;
int age = 18;

@override
Widget build(BuildContext context) {
return Scaffold(
  appBar: AppBar(
    title: Center(child: Text('BMI CALCULATOR')),
  ),
  body: Column(
    children: [
      Expanded(
        child: Row(
          children: [
            Expanded(
              child: ReusableCard(
                gestureDetector: () {
                  setState(() {
                    selectedCardColor = Gender.male;
                  });
                },
                cardChild: ColumnData1(
                  info: 'MALE',
                  icon: FontAwesomeIcons.mars,
                ),
                colour: selectedCardColor == Gender.male
                    ? kActiveCardColor
                    : kInactiveCardColor,
              ),
            ),
            Expanded(
              child: ReusableCard(
                gestureDetector: () {
                  setState(() {
                    selectedCardColor = Gender.female;
                  });
                },
                cardChild: ColumnData1(
                  info: 'FEMALE',
                  icon: FontAwesomeIcons.venus,
                ),
                colour: selectedCardColor == Gender.female
                    ? kActiveCardColor
                    : kInactiveCardColor,
              ),
            ),
          ],
        ),
      ),
      Expanded(
        child: ReusableCard(
          colour: kActiveCardColor,
          cardChild: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                'HEIGHT',
                style: kLabelTextStyle,
              ),
              Row(
                mainAxisAlignment: MainAxisAlignment.center,
                crossAxisAlignment: CrossAxisAlignment.baseline,
                textBaseline: TextBaseline.alphabetic,
                children: [
                  Text(height.toString(), style: kNumberTextStyle),
                  Text('cm', style: kLabelTextStyle),
                ],
              ),
              SliderTheme(
                data: SliderThemeData(
                    activeTrackColor: Colors.white,
                    thumbColor: Color(0xFFDD0059),
                    overlayColor: Color(0x29DD0059),
                    thumbShape: RoundSliderThumbShape(
                      enabledThumbRadius: 18,
                    ),
                    overlayShape:
                        RoundSliderOverlayShape(overlayRadius: 30)),
                child: Slider(
                  min: 120,
                  max: 220,
                  value: height.toDouble(),
                  inactiveColor: Color(0xFF8D8E98),
                  onChanged: (double newValue) {
                    setState(() {
                      height = newValue.round();
                    });
                  },
                ),
              )
            ],
          ),
        ),
      ),
      Expanded(
        child: Row(
          children: [
            Expanded(
              child: ReusableCard(
                colour: kActiveCardColor,
                cardChild: ColumnWidgetForWeightAndAge(
                  info: 'WEIGHT',
                  number: weight,
                ),
              ),
            ),
            Expanded(
              child: ReusableCard(
                colour: kActiveCardColor,
                cardChild: ColumnWidgetForWeightAndAge(
                  info: 'AGE',
                  number: age,
                ),
              ),
            ),
          ],
        ),
      ),
      Container(
        margin: EdgeInsets.only(top: kContainerMarginTop),
        color: Color(0xFFDD0059),
        height: kBottomContainerHeight,
        width: double.infinity,
      )
    ],
  ),
);
}
}

1 Answers1

2

When you change the Height slider, it calls setState, which rebuilds the whole Widget InputPage. Since ColumnWidgetForWeightAndAge is a child of that widget, it also rebuilds with the values you pass to it, which are still 6 and 18 in the InputPage, which is why it gets reinitialized.

There are a few issues with your code:

  • You should refactor so that setState only rebuilds parts of the UI that actually needs rebuild. For instance, the Slider should be be refactored in a separated Widget. That will already make things a bit clearer and is good practice.

  • In ColumnWidgetForWeightAndAge the int number; is not final, which should generate a warning. Make it final, this will be the initial value that the Widget receives. Then in the _ColumnWidgetForWeightAndAgeState, create an initState method to initialize a local variable myNumber that will receive the widget.number as initial value.

  • If you want to update a variable in a parent widget, you have a to pass a callback to its child (such as void onChange(int newValue)=>weight=newValue;), that you will call from the child widget each time the value updates. So your onPressed will become:

     onPressed: () {
       setState(() {
         if (myNumber > 0) {
           myNumber++;
         }
       });
       print(myNumber);
       widget.callback(myNumber);
     }