Search code examples
fluttergetter-setter

Why does slider value return null?


I'm building a page with multiple styled sliders, so I made a separate SliderWidget class. The slider itself behaves normally, but when I try to print the value of the slider to console, it returns null as flutter: null.

I've tried putting specific int values into my currentValue variable (in the SliderWidget class) to test with no luck, so I'm pretty sure that the problem is the getter itself, but I can't figure out what is wrong. I'm pretty new to flutter, so it's very possible I did something stupid.

Here is the slider object:

SliderWidget moodSlider = new SliderWidget(
      sliderHeight: 48,
      min: 0,
      max: 10,
      color1: 0xFF9BC1BC,
      color2: 0xFF9BC1BC);

Here is the SliderWidget class:

import 'package:first_tutorial/MoodUpdate/custom_thumb_circle.dart';
import 'package:flutter/material.dart';

class SliderWidget extends StatefulWidget {
  final double sliderHeight;
  final int min;
  final int max;
  final fullWidth;
  final int color1;
  final int color2;
  final int number;

  SliderWidget(
      {this.sliderHeight,
      this.max,
      this.min,
      this.fullWidth = false,
      this.color1,
      this.color2,
      this.number});

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

class _SliderWidgetState extends State<SliderWidget> {
  double currentValue = 0;

  int get number => currentValue.round();

  @override
  Widget build(BuildContext context) {
    double paddingFactor = .2;

    if (this.widget.fullWidth) paddingFactor = .3;

    return Container(
      width: this.widget.fullWidth
          ? double.infinity
          : (this.widget.sliderHeight) * 5.5,
      height: (this.widget.sliderHeight),
      decoration: new BoxDecoration(
        borderRadius: new BorderRadius.all(
          Radius.circular((this.widget.sliderHeight * .3)),
        ),
        gradient: new LinearGradient(
            colors: [
              Color(this.widget.color1),
              Color(this.widget.color2),
            ],
            begin: const FractionalOffset(0.0, 0.0),
            end: const FractionalOffset(1.0, 1.00),
            stops: [0.0, 1.0],
            tileMode: TileMode.clamp),
      ),
      child: Padding(
        padding: EdgeInsets.fromLTRB(this.widget.sliderHeight * paddingFactor,
            2, this.widget.sliderHeight * paddingFactor, 2),
        child: Row(
          children: <Widget>[
            Text(
              '${this.widget.min}',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize: this.widget.sliderHeight * .3,
                fontWeight: FontWeight.w700,
                color: Colors.white,
              ),
            ),
            SizedBox(
              width: this.widget.sliderHeight * .1,
            ),
            Expanded(
              child: Center(
                child: SliderTheme(
                  data: SliderTheme.of(context).copyWith(
                    activeTrackColor: Colors.white.withOpacity(1),
                    inactiveTrackColor: Colors.white.withOpacity(.5),
                    trackHeight: 4.0,
                    thumbShape: CustomSliderThumbCircle(
                      thumbRadius: this.widget.sliderHeight * .4,
                      darkColor: this.widget.color1,
                      min: this.widget.min,
                      max: this.widget.max,
                    ),
                    overlayColor: Colors.white.withOpacity(.4),
                  ),
                  child: Slider(
                      value: currentValue,
                      onChanged: (value) {
                        setState(() {
                          currentValue = value;
                        });
                      }),
                ),
              ),
            ),
            SizedBox(
              width: this.widget.sliderHeight * .1,
            ),
            Text(
              '${this.widget.max}',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize: this.widget.sliderHeight * .3,
                fontWeight: FontWeight.w700,
                color: Colors.white,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

Edit: I'm printing it to the console within this widget. It's at the bottom in the onPressed parameter:

    @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('My Mood', style: TextStyle(fontFamily: 'WorkSans')),
        backgroundColor: PrimaryColor,
      ),
      backgroundColor: Color(0xFFF4F1BB),
      body: Column(
        children: <Widget>[
          SizedBox(height: 20),
          //Mood title
          Align(
              alignment: Alignment.center,
              child: Text('How are you feeling?',
                  style: TextStyle(
                      color: Colors.grey[800],
                      fontSize: 20,
                      fontFamily: 'WorkSans'))),
          SizedBox(height: 20),
          //Mood slider
          Align(
              alignment: Alignment.center,
              child:moodSlider),
          SizedBox(height: 20),
          //Sleep title
          Align(
              alignment: Alignment.center,
              child: Text('How long did you sleep?',
                  style: TextStyle(
                      color: Colors.grey[800],
                      fontSize: 20,
                      fontFamily: 'WorkSans'))),
          SizedBox(height: 20),
          //Sleep slider
          Align(
              alignment: Alignment.center,
              child: //SliderWidget(
                  //     sliderHeight: 48,
                  //     min: 0,
                  //     max: 12,
                  //     color1: 0xFF766E87,
                  //     color2: 0xFF766E87)
                  sleepSlider),
          SizedBox(height: 20),
          //Save button
          Align(
              alignment: Alignment.bottomCenter,
              child: RaisedButton(
                child: Text('Save'),
                textColor: Colors.white,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10)),
                color: PrimaryColor,
                onPressed: () {
                  print(moodSlider.number);
                }, //_save(moodValue, sleepValue),
              )),
        ],
      ),
    );
  }

Solution

  • I see one getter named number defined in your code..

    int get number => currentValue.round();
    

    ..which is defined in _SliderWidgetState class. Not in SliderWidget class. These 2 are 2 different classes. So when you write moodSlider.number, you are not calling the above getter. Because moodSlider is an instance of SliderWidget class and the getter is defined in the other class. Instead, by writing moodSlider.number, what you are doing is - you are accessing the member variable number of the SliderWidget class..

    class SliderWidget extends StatefulWidget {
      final double sliderHeight;
      final int min;
      final int max;
      final fullWidth;
      final int color1;
      final int color2;
      final int number;         //<-- this one here
    
      SliderWidget(
          {this.sliderHeight,
          this.max,
          this.min,
          this.fullWidth = false,
          this.color1,
          this.color2,
          this.number});
    
      @override
      _SliderWidgetState createState() => _SliderWidgetState();
    }
    

    ..and this member variable number is never assigned a value. That is why it always prints null.

    Edit:

    For this to work, we can add an onChanged callback to the SliderWidget, just like the Slider widget has. We can make this callback to accept a int value parameter, so we can round it from inside _SliderWidgetState and pass to the callback. I made a demo on dartpad. You can see it here - https://dartpad.dev/dc8fd327ff5b94edff6c6f6fe3fea17c