为什么滑块值 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。因为 moodSlider
是 SliderWidget
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
回调中,您将获得滑块的值。
我正在构建一个包含多个样式滑块的页面,因此我制作了一个单独的 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。因为 moodSlider
是 SliderWidget
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
回调中,您将获得滑块的值。