为什么滑块值 return 为空?

Why does slider value return null?

我正在构建一个包含多个样式滑块的页面,因此我制作了一个单独的 SliderWidget class。滑块本身运行正常,但是当我尝试将滑块的值打印到控制台时,它 returns null as flutter: null.

我已经尝试将特定的 int 值放入我的 currentValue 变量(在 SliderWidget class 中)进行测试,但没有成功,所以我很确定问题出在 getter 本身,但我不知道出了什么问题。我是 flutter 的新手,所以我很可能做了一些愚蠢的事情。

这是滑块对象:

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

这是 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,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

编辑:我正在将其打印到此小部件内的控制台。它位于 onPressed 参数的底部:

    @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),
              )),
        ],
      ),
    );
  }

我看到你的代码中定义了一个名为 number 的 getter..

int get number => currentValue.round();

..在_SliderWidgetState class中定义。不在 SliderWidget class 中。这 2 个是 2 个不同的 classes。所以当你写moodSlider.number的时候,你并不是在调用上面的getter。因为 moodSliderSliderWidget class 的实例,而 getter 是在另一个 class 中定义的。相反,通过编写 moodSlider.number,您正在做的是 - 您正在访问 SliderWidget class..

的成员变量 number
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();
}

..并且这个成员变量number从来没有被赋值。这就是为什么它总是打印 null.

编辑:

为此,我们可以向 SliderWidget 添加一个 onChanged 回调,就像 Slider 小部件一样。我们可以让这个回调接受一个 int 值参数,所以我们可以从 _SliderWidgetState 内部舍入它并传递给回调。我在 dartpad 上做了一个演示。你可以在这里看到它 - https://dartpad.dev/dc8fd327ff5b94edff6c6f6fe3fea17c

正如@JigarPatel 所说,您不是在调用 State class 的 getter,而是从 SliderWidget class 调用它其数值为null

您可以尝试将 SliderWidget 更新为 Stateless Widget 请参见下面的示例:

class SliderWidget extends StatelessWidget {
  final double sliderHeight;
  final int min;
  final int max;
  final fullWidth;
  final int color1;
  final int color2;
  final double currentValue;
  final ValueChanged<double> onChanged; 
  
  SliderWidget(
      {this.sliderHeight,
      this.max,
      this.min,
      this.fullWidth = false,
      this.color1,
      this.color2,
      this.currentValue, this.onChanged});

  

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

    if ( fullWidth) paddingFactor = .3;

    return Container(
      width:  fullWidth
          ? double.infinity
          : ( sliderHeight) * 5.5,
      height: ( sliderHeight),
      decoration: new BoxDecoration(
        borderRadius: new BorderRadius.all(
          Radius.circular(( sliderHeight * .3)),
        ),
        gradient: new LinearGradient(
            colors: [
              Color( color1),
              Color( 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( sliderHeight * paddingFactor,
            2,  sliderHeight * paddingFactor, 2),
        child: Row(
          children: <Widget>[
            Text(
              '$min',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize:  sliderHeight * .3,
                fontWeight: FontWeight.w700,
                color: Colors.white,
              ),
            ),
            SizedBox(
              width:  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:  sliderHeight * .4,
                      darkColor:  color1,
                      min:  min,
                      max:  max,
                    ),
                    overlayColor: Colors.white.withOpacity(.4),
                  ),
                  child: Slider(
                      value: currentValue,
                      onChanged: onChanged),
                ),
              ),
            ),
            SizedBox(
              width:  sliderHeight * .1,
            ),
            Text(
              '$max',
              textAlign: TextAlign.center,
              style: TextStyle(
                fontSize:  sliderHeight * .3,
                fontWeight: FontWeight.w700,
                color: Colors.white,
              ),
            ),
          ],
        ),
      ),
    );
  }
}

onChanged 回调中,您将获得滑块的值。