Reputation:
I am practicing a BMI app. I have completed everything, currently i am abstracting my code. I have created a class called ReusableAgeWeightCard and i have inserted function over there onTapDownMinus, onTapUp, onTapCancel, onPressMinus, onTapDownPlus, onPressPlus. I don't know what error i have made with the TapDownDetails details?
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');
}),
This is the function
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;
}
});
}
}
This is the error
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
════════════════════════════════════════════════════════════════════════════════════════════════════
Upvotes: 1
Views: 6266
Reputation: 3407
The function you're passing to GestureDetector's onTapDown parameter should be of type "Function(TapDownDetails details)". Currently you're passing VoidCallback in to it.
I've left only the parts that need to be corrected.
class ReusableAgeWeightCard extends StatelessWidget {
final GestureTapDownCallback onTapDownMinus;
final GestureTapDownCallback onTapDownPlus;
}
And when you're using your new widget - don't forget to pass the right function in to those params.
In your example above, the "onTapDownPlus" definition is incorrect.
ReusableAgeWeightCard(
onTapDownMinus: (details) {}, // This one is correct in your code
onTapDownPlus: (details) {}, // This one has to be fixed
)
If you're not going to use "details" in the function code, you can always define the function as in example below (using "empty" parameters).
ReusableAgeWeightCard(
onTapDownMinus: (_) {},
onTapDownPlus: (_) {},
)
UPD: Added the full widget code with the "stack widget at index 0" fix.
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,
),
),
),
],
)
],
),
],
),
);
}
}
Upvotes: 1