我正在练习BMI应用程序。我已经完成了所有工作,目前正在提取代码。我创建了一个名为ReusableAgeWeightCard的类,并在该处插入了onTapDownMinus,onTapUp,onTapCancel,onPressMinus,onTapDownPlus,onPressPlus函数。我不知道我对TapDownDetails详细信息犯了什么错误?
class ReusableAgeWeightCard extends StatelessWidget {
final Widget changeMode;
final String label;
final String unit;
final int si;
final Function onTapDownMinus;
final Function onTapUp;
final Function onTapCancel;
final Function onPressMinus;
final Function onTapDownPlus;
final Function onPressPlus;
ReusableAgeWeightCard({
@required this.label,
this.changeMode,
this.unit,
@required this.si,
@required this.onTapDownMinus,
@required this.onTapUp,
@required this.onTapCancel,
@required this.onPressMinus,
@required this.onTapDownPlus,
@required this.onPressPlus,
});
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(6.0),
margin: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: kActiveCardColor,
borderRadius: BorderRadius.circular(15.0),
),
child: Stack(
alignment: Alignment.topRight,
children: <Widget>[
changeMode,
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
label,
style: kLabelTextStyle,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Text(
si.toString(),
style: kNumberMediumTextStyle,
),
Text(
unit,
style: kLabelTextStyle,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTapDown: onTapDownMinus,
onTapUp: onTapUp,
onTapCancel: onTapCancel,
onTap: onPressMinus,
child: RawMaterialButton(
elevation: 6.0,
fillColor: Color(0xff4c4f5e),
shape: CircleBorder(),
constraints: BoxConstraints.tightFor(
height: 56.0,
width: 56.0,
),
child: Icon(
FontAwesomeIcons.minus,
size: 25.0,
color: Colors.white,
),
),
),
SizedBox(
width: 10.0,
),
GestureDetector(
onTapDown: onTapDownPlus,
onTapUp: onTapUp,
onTapCancel: onTapCancel,
onTap: onPressPlus,
child: RawMaterialButton(
elevation: 6.0,
fillColor: Color(0xff4c4f5e),
shape: CircleBorder(),
constraints: BoxConstraints.tightFor(
height: 56.0,
width: 56.0,
),
child: Icon(
FontAwesomeIcons.plus,
size: 25.0,
color: Colors.white,
),
),
),
],
)
],
),
],
),
);
}
}
ReusableAgeWeightCard(
label: 'AGE',
unit: '',
si: age,
onTapDownMinus: (TapDownDetails details) {
minusOnTapDown('age');
},
onTapUp: (TapUpDetails details) {
cancelTimer();
},
onTapCancel: () {
cancelTimer();
},
onPressMinus: () {
minusOnPress('age');
},
onTapDownPlus: () {
plusOnTapDown('age');
},
onPressPlus: () {
plusOnPress('age');
}),
这是功能
void minusOnTapDown(String parameter) {
if (parameter == 'age') {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
age--;
if (age <= 1) {
timer.cancel();
age = 1;
}
});
});
} else if (parameter == 'pound') {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
pound--;
if (pound <= 1) {
timer.cancel();
pound = 1;
}
});
});
} else {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
kg--;
if (kg <= 1) {
timer.cancel();
kg = 1;
}
});
});
}
}
void plusOnTapDown(String parameter) {
if (parameter == 'age') {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
age++;
if (age > 117) {
timer.cancel();
age = 117;
}
});
});
} else if (parameter == 'pound') {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
pound++;
if (pound >= 450) {
timer.cancel();
}
});
});
} else {
timer = Timer.periodic(Duration(milliseconds: 100), (timer) {
setState(() {
kg++;
if (kg >= 204) {
timer.cancel();
kg = 204;
}
});
});
}
}
void cancelTimer() {
setState(() {
timer.cancel();
});
}
void minusOnPress(String parameter) {
if (parameter == 'age') {
setState(() {
age--;
if (age <= 1) {
age = 1;
}
});
} else if (parameter == 'pound') {
setState(() {
pound--;
if (pound <= 1) {
pound = 1;
}
});
} else {
setState(() {
kg--;
if (kg <= 1) {
kg = 1;
}
});
}
}
void plusOnPress(String parameter) {
if (parameter == 'age') {
setState(() {
age++;
if (age >= 117) {
age = 117;
}
});
} else if (parameter == 'pound') {
setState(() {
pound++;
if (pound >= 450) {
pound = 450;
}
});
} else {
setState(() {
kg++;
if (kg >= 204) {
kg = 204;
}
});
}
}
这是错误
Performing hot restart...
Syncing files to device Android SDK built for x86...
Restarted application in 3,474ms.
I/flutter ( 2903): ══╡ EXCEPTION CAUGHT BY WIDGETS LIBRARY ╞═══════════════════════════════════════════════════════════
I/flutter ( 2903): The following _TypeError was thrown building ReusableAgeWeightCard(dirty):
I/flutter ( 2903): type '() => Null' is not a subtype of type '(TapDownDetails) => void'
I/flutter ( 2903):
I/flutter ( 2903): The relevant error-causing widget was:
I/flutter ( 2903): ReusableAgeWeightCard file:///D:/Other/App/Flutter/bmi/lib/screen/input_page.dart:420:26
I/flutter ( 2903):
I/flutter ( 2903): When the exception was thrown, this was the stack:
I/flutter ( 2903): #0 ReusableAgeWeightCard.build (package:bmi/components/reusable_age_weight_card.dart:92:32)
I/flutter ( 2903): #1 StatelessElement.build (package:flutter/src/widgets/framework.dart:4576:28)
I/flutter ( 2903): #2 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4502:15)
I/flutter ( 2903): #3 Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5)
I/flutter ( 2903): #4 ComponentElement._firstBuild (package:flutter/src/widgets/framework.dart:4481:5)
I/flutter ( 2903): #5 ComponentElement.mount (package:flutter/src/widgets/framework.dart:4476:5)
I/flutter ( 2903): ... Normal element mounting (7 frames)
I/flutter ( 2903): #12 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 2903): #13 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5947:32)
I/flutter ( 2903): ... Normal element mounting (7 frames)
I/flutter ( 2903): #20 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 2903): #21 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5947:32)
I/flutter ( 2903): ... Normal element mounting (19 frames)
I/flutter ( 2903): #40 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 2903): #41 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5947:32)
I/flutter ( 2903): ... Normal element mounting (193 frames)
I/flutter ( 2903): #234 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 2903): #235 MultiChildRenderObjectElement.mount (package:flutter/src/widgets/framework.dart:5947:32)
I/flutter ( 2903): ... Normal element mounting (238 frames)
I/flutter ( 2903): #473 Element.inflateWidget (package:flutter/src/widgets/framework.dart:3446:14)
I/flutter ( 2903): #474 Element.updateChild (package:flutter/src/widgets/framework.dart:3214:18)
I/flutter ( 2903): #475 RenderObjectToWidgetElement._rebuild (package:flutter/src/widgets/binding.dart:1148:16)
I/flutter ( 2903): #476 RenderObjectToWidgetElement.mount (package:flutter/src/widgets/binding.dart:1119:5)
I/flutter ( 2903): #477 RenderObjectToWidgetAdapter.attachToRenderTree.<anonymous closure> (package:flutter/src/widgets/binding.dart:1061:17)
I/flutter ( 2903): #478 BuildOwner.buildScope (package:flutter/src/widgets/framework.dart:2607:19)
I/flutter ( 2903): #479 RenderObjectToWidgetAdapter.attachToRenderTree (package:flutter/src/widgets/binding.dart:1060:13)
I/flutter ( 2903): #480 WidgetsBinding.attachRootWidget (package:flutter/src/widgets/binding.dart:941:7)
I/flutter ( 2903): #481 WidgetsBinding.scheduleAttachRootWidget.<anonymous closure> (package:flutter/src/widgets/binding.dart:922:7)
I/flutter ( 2903): (elided 11 frames from class _RawReceivePortImpl, class _Timer, dart:async, and dart:async-patch)
I/flutter ( 2903):
I/flutter ( 2903): ════════════════════════════════════════════════════════════════════════════════════════════════════
I/flutter ( 2903): Another exception was thrown: type '() => Null' is not a subtype of type '(TapDownDetails) => void'
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following _TypeError was thrown building ReusableAgeWeightCard(dirty):
type '() => Null' is not a subtype of type '(TapDownDetails) => void'
The relevant error-causing widget was:
ReusableAgeWeightCard file:///D:/Other/App/Flutter/bmi/lib/screen/input_page.dart:420:26
When the exception was thrown, this was the stack:
#0 ReusableAgeWeightCard.build (package:bmi/components/reusable_age_weight_card.dart:92:32)
#1 StatelessElement.build (package:flutter/src/widgets/framework.dart:4576:28)
#2 ComponentElement.performRebuild (package:flutter/src/widgets/framework.dart:4502:15)
#3 Element.rebuild (package:flutter/src/widgets/framework.dart:4218:5)
#4 StatelessElement.update (package:flutter/src/widgets/framework.dart:4583:5)
...
════════════════════════════════════════════════════════════════════════════════════════════════════
════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
type '() => Null' is not a subtype of type '(TapDownDetails) => void'
The relevant error-causing widget was:
ReusableAgeWeightCard file:///D:/Other/App/Flutter/bmi/lib/screen/input_page.dart:487:32
════════════════════════════════════════════════════════════════════════════════════════════════════
答案 0 :(得分:0)
您要传递给GestureDetector的onTapDown参数的函数应为“ Function(TapDownDetails details)”类型。目前,您正在将VoidCallback传递给它。
我只留下了需要纠正的部分。
class ReusableAgeWeightCard extends StatelessWidget {
final GestureTapDownCallback onTapDownMinus;
final GestureTapDownCallback onTapDownPlus;
}
当您使用新的小部件时-不要忘记将正确的函数传递给这些参数。
在上面的示例中,“ onTapDownPlus”定义不正确。
ReusableAgeWeightCard(
onTapDownMinus: (details) {}, // This one is correct in your code
onTapDownPlus: (details) {}, // This one has to be fixed
)
如果您不打算在功能代码中使用“详细信息”,则始终可以按以下示例中的说明定义功能(使用“空”参数)。
ReusableAgeWeightCard(
onTapDownMinus: (_) {},
onTapDownPlus: (_) {},
)
UPD:添加了完整的窗口小部件代码,并修复了“索引为0的堆栈窗口小部件”。
class ReusableAgeWeightCard extends StatelessWidget {
final Widget changeMode;
final String label;
final String unit;
final int si;
final GestureTapDownCallback onTapDownMinus;
final Function onTapUp;
final Function onTapCancel;
final Function onPressMinus;
final GestureTapDownCallback onTapDownPlus;
final Function onPressPlus;
ReusableAgeWeightCard({
@required this.label,
this.changeMode,
this.unit,
@required this.si,
@required this.onTapDownMinus,
@required this.onTapUp,
@required this.onTapCancel,
@required this.onPressMinus,
@required this.onTapDownPlus,
@required this.onPressPlus,
});
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(6.0),
margin: EdgeInsets.all(15.0),
decoration: BoxDecoration(
color: kActiveCardColor,
borderRadius: BorderRadius.circular(15.0),
),
child: Stack(
alignment: Alignment.topRight,
children: <Widget>[
if( changeMode != null) changeMode, // <-- Fixed this line with a conditional rendering
Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: <Widget>[
Text(
label,
style: kLabelTextStyle,
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic,
children: <Widget>[
Text(
si.toString(),
style: kNumberMediumTextStyle,
),
Text(
unit,
style: kLabelTextStyle,
),
],
),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
GestureDetector(
onTapDown: onTapDownMinus,
onTapUp: onTapUp,
onTapCancel: onTapCancel,
onTap: onPressMinus,
child: RawMaterialButton(
elevation: 6.0,
fillColor: Color(0xff4c4f5e),
shape: CircleBorder(),
constraints: BoxConstraints.tightFor(
height: 56.0,
width: 56.0,
),
child: Icon(
FontAwesomeIcons.minus,
size: 25.0,
color: Colors.white,
),
),
),
SizedBox(
width: 10.0,
),
GestureDetector(
onTapDown: onTapDownPlus,
onTapUp: onTapUp,
onTapCancel: onTapCancel,
onTap: onPressPlus,
child: RawMaterialButton(
elevation: 6.0,
fillColor: Color(0xff4c4f5e),
shape: CircleBorder(),
constraints: BoxConstraints.tightFor(
height: 56.0,
width: 56.0,
),
child: Icon(
FontAwesomeIcons.plus,
size: 25.0,
color: Colors.white,
),
),
),
],
)
],
),
],
),
);
}
}