how to inject function to other class in flutter - function

I want to print 'test' when clicking MyButton
I made constructs with a function in my class but didn't work
please help me
here is my code
Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'bla bla bla',
),
MyButton((){print('test');}, 'my button')
],
),
I'm made a StatefulWidget class I called it MyButton
import 'package:flutter/material.dart';
class MyButton extends StatefulWidget {
Function buttonFunction;
String buttonName;
MyButton(this.buttonFunction,this.buttonName);
#override
_MyButtonState createState() => _MyButtonState();
}
class _MyButtonState extends State<MyButton> {
#override
Widget build(BuildContext context) {
String name=widget.buttonName;
return Container(
width: 200,
child: RaisedButton(
color: Colors.red,
onPressed: () {
widget.buttonFunction;
print('clicked $name');
},
textColor: Colors.white,
child: Text("$name",
style: TextStyle(fontSize: 18,),
),
),
);
}
}

You are missing the parenthesis "()" to call the function, instead you are just referencing it.
You are also setting a variable inside the build method which is the wrong place to declare variables, as it will re-run many times and be re-declared unnecessarily and become expensive. If you want to access the property of a value inside a String you just have to use `"String ${widget.myStringVariable}.".
I've modified your code to reflect these changes:
class _MyButtonState extends State<MyButton> {
#override
Widget build(BuildContext context) {
return Container(
width: 200,
child: RaisedButton(
color: Colors.red,
onPressed: () {
widget.buttonFunction();
print('clicked $name');
},
textColor: Colors.white,
child: Text("${widget.buttonName}",
style: TextStyle(fontSize: 18,),
),
),
);
}
}

Related

How to generate a List to the second screen in flutter from a JSON?

I am trying to create a list from the value inside a JSON. I can get the length but not for the data. My main goal is to create a list of items based on their popularity.
child: Row(
children: [
...List.generate(
"items"[0].length,
(index) {
if (["items"][index].isPopular) { // here I want to generate a list for the value isPopular
return BreakfastCard(breakfast: ('items'[0] as Map<String, dynamic>[index]); // Here I want to call the function from other screen
}
And when I tried to change the code to this
"items"[0].length,
(index) {
if (["items"][index][isPopular]) { // the error here is *Conditions must have a static type of 'bool'.*
return BreakfastCard(breakfast: ['items'][0][index]); // the error here is *The argument type 'String' can't be assigned to the parameter type 'Breakfast'.*
The JSON data is like this
{
"items":[{
"id": 1,
"rating": "0.0",
"images": [
"assets/images/cilantro.png"
],
"title": "Cilantro and Kale Pesto Toast with a Fried Egg",
"time": 15,
"description": "Sliced bread is the perfect blank canvas, ready to be loaded up with virtuous ingredients.",
" rating": "4.8",
"isFavorite": false,
"isPopular": true,
}]
}
Here is my code for the card. In this part, there were no error and it show what I want.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:fema/models/Breakfast.dart';
import 'package:flutter/services.dart';
import 'package:flutter_svg/flutter_svg.dart';
import '../constants.dart';
import '../size_config.dart';
class BreakfastCard extends StatefulWidget {
BreakfastCard({
Key? key,
this.width = 140,
this.aspectRetio = 1.02,
required this.breakfast,
}) : super(key: key);
final double width, aspectRetio;
Breakfast breakfast;
#override
_BreakfastCardState createState() => _BreakfastCardState();
}
class _BreakfastCardState extends State<BreakfastCard> {
#override
Widget build(BuildContext context) {
Future<String> _loadloadBreakfastAsset() async {
return await rootBundle.loadString('assets/breakfast.json');
}
Future<BreakfastCard> loadBreakfast() async {
String jsonAddress = await _loadloadBreakfastAsset();
final jsonResponse = json.decode(jsonAddress);
// This now updates the breakfast property in the main class.
widget.breakfast = Breakfast.fromJson(jsonResponse);
// This return value is thrown away, but this line is necessary to
// resolve the Future call that FutureBuilder is waiting on.
return Future<BreakfastCard>.value();
}
SizeConfig().init(context);
return FutureBuilder(
future: loadBreakfast(),
builder: (BuildContext, AsyncSnapshot<dynamic>snapshot){
return Padding(
padding: EdgeInsets.only(left: getProportionateScreenWidth(20)),
child: SizedBox(
width: getProportionateScreenWidth(140),
child: GestureDetector(
onTap: (){},
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
AspectRatio(
aspectRatio: 1.02,
child: Container(
padding: EdgeInsets.all(getProportionateScreenWidth(20)),
decoration: BoxDecoration(
color: kSecondaryColor.withOpacity(0.1),
borderRadius: BorderRadius.circular(15),
),
child: Hero(
tag: widget.breakfast.id.toString(),
child: Image.asset(widget.breakfast.images[0]),
),
),
),
const SizedBox(height: 10),
Text(
widget.breakfast.title,
style: const TextStyle(color: Colors.black),
maxLines: 2,
),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
"${widget.breakfast.calories} cal |",
style: TextStyle(
fontSize: getProportionateScreenWidth(18),
fontWeight: FontWeight.bold,
color: kPrimaryColor,
),
),
Text(
"${widget.breakfast.time} min",
style: TextStyle(
fontSize: getProportionateScreenWidth(18),
fontWeight: FontWeight.w600,
color: kPrimaryColor,
),
),
InkWell(
borderRadius: BorderRadius.circular(50),
onTap: () { widget.breakfast.isFavorite = !widget.breakfast.isFavorite;},
child: Container(
padding: EdgeInsets.all(getProportionateScreenWidth(8)),
height: getProportionateScreenWidth(28),
width: getProportionateScreenWidth(28),
child: SvgPicture.asset(
"assets/icons/Heart Icon_2.svg",
color: widget.breakfast.isFavorite
? const Color(0xFFFF4848)
: const Color(0xFFDBDEE4),
),
),
),
],
)
],
),
),
),
);
}
);
}
}
And my problem is in here. Where the list will be generated. I am new to flutter and I have difficulties to solve the problem. In here I can correctly create a function to fetch the data from the BreakfastCard.
import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:fema/components/breakfast_card.dart';
import 'package:fema/models/Breakfast.dart';
import 'package:flutter/services.dart';
import '../../../size_config.dart';
import 'section_title.dart';
class Breakfast extends StatelessWidget {
const Breakfast({Key? key}) : super(key: key);
#override
Widget build(BuildContext context) {
Future<String> _loadloadBreakfastAsset() async {
return await rootBundle.loadString('assets/breakfast.json');
}
Future<Breakfast> loadBreakfast() async {
String jsonAddress = await _loadloadBreakfastAsset();
Map<String,dynamic> map = json.decode(jsonAddress);
List<dynamic> items = map["items"];
// This return value is thrown away, but this line is necessary to
// resolve the Future call that FutureBuilder is waiting on.
return Future<Breakfast>.value();
}
return FutureBuilder(
future: loadBreakfast(),
builder: (BuildContext, AsyncSnapshot<dynamic>snapshot){
return Column(
children: [
Padding(
padding:
EdgeInsets.symmetric(horizontal: getProportionateScreenWidth(20)),
child: SectionTitle(title: "BREAKFAST", press: () {}),
),
SizedBox(height: getProportionateScreenWidth(20)),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: [
...List.generate(
items[0].length,
(index) {
if (items[index].isPopular) {
return BreakfastCard(breakfast: );
}
return const SizedBox
.shrink(); // here by default width and height is 0
},
),
SizedBox(width: getProportionateScreenWidth(20)),
],
),
)
],
);
});
}
}
You need to put "items" into a Map first. You are trying to use the String object "items" to populate your list. You want the data from the json to populate it.
Get the data into a usable object first.
Map<String, dynamic> map = jsonDecode(data);
List<dynamic> items = map["items"];
Then you can populate your list from that data.
child: Row(
children: [
...List.generate(
items.length,
(index) {
if (items[index].isPopular) {
return BreakfastCard(breakfast: (items[0]));
}
Your errors are from trying to use json data improperly as the conditional for an if statement.
The other error is because you are trying to send a String as an argument for a Breakfast object when it needs something else (I don't know what that is. You didn't post what a BreakfastCard class looks like at the time I wrote this.)
Dart and Flutter documentation is very good. Try this out https://flutter.dev/docs/development/data-and-backend/json

How can I pass a buttonClick to a Function on another Page?

I'm trying to pass a simple buttonpress to performe something in another class. The point is to use one page for several different functions, instead of having one page for every function.
Right now the navigation to the textDeclaration-page works fine, but I can't get the right function do do its job.
If I press the First Button, the info from FirstButton Widget should display on the textDeclaration page, and if I press the Second Button, the info from SecondButton Widget should pop up on the displayText-page.
Main:
import 'package:flutter/material.dart';
import 'homePage.dart';
void main()=>runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
HomePage:
import 'package:flutter/material.dart';
import 'textDeclaration.dart';
class HomePage extends StatefulWidget {
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
Function buttonChoice;
Widget outlineButton(String buttonName) {
return SizedBox(
height: 60.0,
width: 225.0,
child: OutlineButton(
highlightedBorderColor: Colors.lightBlueAccent,
child: Text(buttonName,
style: TextStyle(fontSize: 17.0, fontWeight:
FontWeight.bold)),
borderSide: BorderSide(
color: Colors.blue,
width: 2.0,
),
onPressed: () {
navigate(buttonName, buttonChoice);
}),
);
}
void navigate(String buttonName, Function buttonChoice) {
setState(() {
Navigator.of(context).popUntil(ModalRoute.withName('/'));
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => TextDeclaration(
buttonName: buttonName,
buttonChoice: buttonChoice,
)));
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('HOME PAGE')),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
outlineButton('First Button'),
outlineButton('Second Button'),
],
),
),
);
}
}
textDeclarationPage:
import 'package:flutter/material.dart';
class TextDeclaration extends StatefulWidget {
final String buttonName;
final Function buttonChoice;
TextDeclaration({this.buttonName, this.buttonChoice});
#override
_TextDeclarationState createState() => _TextDeclarationState();
}
class _TextDeclarationState extends State<TextDeclaration> {
String buttonName = "";
buttonChoice(String buttonName) {
if (buttonName == 'First Button') {
firstButton(buttonName);
} else if (buttonName == 'Second Button') {
secondButton(buttonName);
}
}
Widget firstButton(buttonName) {
return Scaffold(
appBar: AppBar(
title: Text('First Button'),
),
body: Center(
child: Container(
height: 200.0,
width: 200.0,
child: Center(child: Text('First Button Text')),
),
),
);
}
Widget secondButton(buttonName) {
return Scaffold(
appBar: AppBar(
title: Text('Second Button'),
),
body: Center(
child: SizedBox(
height: 200.0,
width: 200.0,
child: Center(
child: Text('Second Button Text'),
),
),
),
);
}
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(color: Colors.blue),
child: buttonChoice(buttonName),
);
}
}
The code runs, but the functions from the different buttons won't work.
Any help at all would be great since I've been stuck with this for a very long time now. Thanks.

issues with input length and buttonclicks

I'm working on a simple math-app for my daughter. Below is some code that you can use if you like (it may not be the most beautiful code, but it works ok and maybe it helps someone).
My issues are:
1) To limit the number of characters (numbers) that the user can type. I only find solutions about this when it comes to textFields (such as maxLength).
2) My refresh-button ("NEXT") is not working at all. The idea is to give the user a new random math-task from the previous arithmetic choice.
3) Currently you can type the wrong answer, click ok and then correct your answer to get a "Correct". The plan is that once you've clicked ok, you won't be able to change your answer. You will only be able to click NEXT. (I plan to implement a counter to this later, that will return the number of correct and false answers after x numbers of tasks).
Any help is highly appreciated (code or what I shall look at). Thank you.
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
.then((_) => runApp(HomePage()));
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'input',
theme: ThemeData(primarySwatch: Colors.purple),
home: FirstClass(),
);
}
}
class FirstClass extends StatefulWidget {
#override
_FirstClassState createState() => _FirstClassState();
}
class _FirstClassState extends State<FirstClass> {
final random = Random();
int a, b, c, sum;
String output;
void changeData(String buttonName) {
setState(() {
a = random.nextInt(10);
b = random.nextInt(10);
if (buttonName == '+') {
sum = a + b;
output = '$a+$b= ';
} else if (buttonName == '-') {
if (a >= b) {
sum = a - b;
output = '$a-$b= ';
} else if (b > a) {
sum = b - a;
output = '$b-$a= ';
}
}
print(sum.toString());
Navigator.of(context).popUntil(ModalRoute.withName('/'));
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => SecondClass(
sum: sum,
refresh: changeData,
output: output,
buttonName: buttonName,
)));
});
}
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(color: Colors.deepPurple),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.transparent,
elevation: 0.0,
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
),
title: Text(
'MATH',
style: TextStyle(fontSize: 25.0),
),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RaisedButton(
child: Text('+', style: TextStyle(fontSize: 24.0)),
onPressed: () => changeData('+')),
RaisedButton(
child: Text('-', style: TextStyle(fontSize: 24.0)),
onPressed: () => changeData('-')),
],
),
),
),
);
}
}
class SecondClass extends StatefulWidget {
final int sum;
final String output;
final String buttonName;
final Function refresh;
SecondClass({this.sum, this.refresh, this.buttonName, this.output});
#override
_SecondClassState createState() => _SecondClassState();
}
class _SecondClassState extends State<SecondClass> {
String output = "";
String _output = "";
String output2 = "";
#override
void initState() {
super.initState();
}
buttonPressed(String buttonText) {
if (buttonText == "<-") {
_output = "";
} else if (buttonText == "OK") {
if (output.isNotEmpty) {
if (output == widget.sum.toString()) {
setState(() {
output2 = 'Correct';
});
} else {
setState(() {
output2 = 'False';
});
}
} else if (buttonText == "NEXT") {
widget.refresh(widget.buttonName);
}
} else {
_output = _output + buttonText;
}
setState(() {
output = _output;
});
print(buttonText);
}
Widget buildButton(String buttonText) {
return Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
child: OutlineButton(
color: Colors.white,
child: Text(
buttonText,
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.bold),
),
onPressed: () => buttonPressed(buttonText)),
),
);
}
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(color: Colors.purple),
child: Column(
children: <Widget>[
Padding(
padding: const EdgeInsets.only(top: 40.0, left: 20.0, right:
20.0),
child: Container(
height: 60.0,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0)),
child: Center(
child: Text(
widget.output + output,
style: TextStyle(
color: Colors.black,
fontSize: 48.0,
fontWeight: FontWeight.bold),
),
)),
),
Padding(
padding: const EdgeInsets.only(top: 20.0, left: 20.0, right:
20.0),
child: Container(
height: 60.0,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0)),
child: Text(
output2,
style: TextStyle(
color: Colors.black,
fontSize: 48.0,
fontWeight: FontWeight.bold),
),
),
),
Expanded(child: Divider()),
Column(
children: <Widget>[
Row(
children: <Widget>[
buildButton('1'),
buildButton('2'),
buildButton('3'),
],
),
Row(
children: <Widget>[
buildButton('4'),
buildButton('5'),
buildButton('6'),
],
),
Row(
children: <Widget>[
buildButton('7'),
buildButton('8'),
buildButton('9'),
],
),
Row(
children: <Widget>[
buildButton('<-'),
buildButton('0'),
buildButton('OK'),
],
),
Row(
children: <Widget>[
buildButton('NEXT'),
],
),
],
),
],
),
);
}
}
Well It's working. It's not the best way to do this but I tried keep your old code base.I really advise make use of some patterns like BLoC to manage the state of the widgets and avoid setState calls.
Was needed split your code in some more classes.
What I have done here??
Create a enum called MathOperation. This enum is used to identify what kind of arithmetic operation the user selected.
The older FirstClass is now OperationSelectorScreen
The older SecondClass is now QuestionAndAnswerScreen
I've created CustomTextField class to implement a simple 'text field' with a max number of characters.
I've implmented MathOperationTask class. This class is an abstraction for arithmetics operations like sum and subtraction. This class holds the numbers involved in operation, his symbol "+" or "-" and the operation results.
There is some comments in source code to guide you, if you need to ask for something feel free to do I will answer when I can. I hope it helps.
import 'dart:math';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
/// enum used to identify math operation types
enum MathOperation { SUM, SUBTRACTION }
void main() {
SystemChrome.setPreferredOrientations([DeviceOrientation.portraitUp])
.then((_) => runApp(HomePage()));
}
class HomePage extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'input',
theme: ThemeData(primarySwatch: Colors.purple),
home: OperationSelectorScreen(),
);
}
}
/// old FirstClass
class OperationSelectorScreen extends StatefulWidget {
#override
_OperationSelectorScreenState createState() => _OperationSelectorScreenState();
}
class _OperationSelectorScreenState extends State<OperationSelectorScreen> {
MathOperation _userSelectedOperation;
void changeData(String buttonName) {
setState(() {
if (buttonName == '+') {
_userSelectedOperation = MathOperation.SUM;
} else if (buttonName == '-') {
_userSelectedOperation = MathOperation.SUBTRACTION;
}
Navigator.of(context).popUntil(ModalRoute.withName('/'));
/// we only need pass to next screen what kind of operation
/// was selected by user
Navigator.of(context).push(MaterialPageRoute(
builder: (context) => QuestionAndAnswerScreen(
operationType: _userSelectedOperation,// operation selected by user ( '+' or '-' )
)));
});
}
#override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(color: Colors.deepPurple),
child: Scaffold(
backgroundColor: Colors.transparent,
appBar: AppBar(
centerTitle: true,
backgroundColor: Colors.transparent,
elevation: 0.0,
leading: IconButton(
icon: Icon(Icons.menu),
onPressed: () {},
),
title: Text(
'MATH',
style: TextStyle(fontSize: 25.0),
),
),
body: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
RaisedButton(
child: Text('+', style: TextStyle(fontSize: 24.0)),
onPressed: () => changeData('+')),
RaisedButton(
child: Text('-', style: TextStyle(fontSize: 24.0)),
onPressed: () => changeData('-')),
],
),
),
),
);
}
}
/// old SecondClass
class QuestionAndAnswerScreen extends StatefulWidget {
final operationType; // if the operations will be (+) or (-)
QuestionAndAnswerScreen({this.operationType});
#override
_QuestionAndAnswerScreenState createState() => _QuestionAndAnswerScreenState();
}
class _QuestionAndAnswerScreenState extends State<QuestionAndAnswerScreen> {
String _userTypedAnswer=""; // numbers that user had typed
String _answerValidationOutput = ""; // will say if the user answer ir correct or wrong(false)
MathOperationTask _currentTask; // current arithmetic operation
// this member controls the back button "<-" activity
// if user had responded the question, this value will be true and
// the button "<-" will not work properly.
bool _isQuestionResponded = false;
#override
void initState() {
super.initState();
//using math operation task generator method to create a new math operation
_currentTask = MathOperationTask.generateMathTask( widget.operationType );
}
buttonPressed(String buttonText) {
// this logic can be improved if we
// transform the custom keyboard in a widget
if (buttonText == "<-") {
if (!_isQuestionResponded){
_changeUserTypedText("");
_changeAnswerValidationText("");
}
}
else if (buttonText == "OK") {
if (_userTypedAnswer.isNotEmpty) {
_isQuestionResponded = true;
if (_userTypedAnswer == _currentTask.results.toString()) {
_changeAnswerValidationText('Correct');
}
else {
_changeAnswerValidationText('False');
}
}
}
else if (buttonText == "NEXT") {
print("new OP");
_spawnArithmeticOperation();
}
else {
///This if statement solves the problem of put in member after question
///responded.If question is NOT responded, OK button not pressed then we update the text.
if (!_isQuestionResponded)
_changeUserTypedText( (_userTypedAnswer + buttonText) );
}
}
/// this mehtod creates a new arithmetic operation and update the screen with
void _spawnArithmeticOperation(){
_currentTask = MathOperationTask.generateMathTask(widget.operationType);
_answerValidationOutput ="";
_userTypedAnswer = "";
_isQuestionResponded = false;
setState(() {});
}
/// method to change and update UI after user type something.
void _changeUserTypedText(String text){
setState(() => _userTypedAnswer = text );
}
/// update the text if the answer is correct, wrong or clean the text.
void _changeAnswerValidationText(String text){
setState(() => _answerValidationOutput = text );
}
Widget buildButton(String buttonText) {
return Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 8.0, right: 8.0, bottom: 8.0),
child: OutlineButton(
color: Colors.white,
child: Text(
buttonText,
style: TextStyle(
color: Colors.white,
fontSize: 20.0,
fontWeight: FontWeight.bold),
),
onPressed: () => buttonPressed(buttonText)),
),
);
}
#override
Widget build(BuildContext context) {
final operationField = CustomTextField( maxLength: 7, // max text length
text: "${_currentTask.firstMember}" // first member of operation
"${_currentTask.operationSymbol}" // operation signal
"${_currentTask.secondMember}= " // second member of math operation
"$_userTypedAnswer",
);
final answerFinalResultsField = CustomTextField(
maxLength: 7,
text: _answerValidationOutput
);
return Container(
decoration: BoxDecoration(color: Colors.purple),
child: Column(
children: <Widget>[
operationField,
answerFinalResultsField,
Expanded(child: Divider()),
_buildKeyboard(),
],
),
);
}
// here i put your keyboard layout..
Widget _buildKeyboard(){
return Column(
children: <Widget>[
Row(
children: <Widget>[
buildButton('1'),
buildButton('2'),
buildButton('3'),
],
),
Row(
children: <Widget>[
buildButton('4'),
buildButton('5'),
buildButton('6'),
],
),
Row(
children: <Widget>[
buildButton('7'),
buildButton('8'),
buildButton('9'),
],
),
Row(
children: <Widget>[
buildButton('<-'),
buildButton('0'),
buildButton('OK'),
],
),
Row(
children: <Widget>[
buildButton('NEXT'),
],
),
],
);
}
}
/// this class represents an arithmetic operation
/// example 3 + 6 = 9
/// 3 is the firstMember, 6 the secondMember and results is 9.
class MathOperationTask {
final firstMember;
final secondMember;
final results; //operation results
final operationSymbol;
// text math symbols constants only to show...
static final String PLUS = "+";
static final String LESS = "-";
MathOperationTask( {this.firstMember, this.secondMember, this.results, this.operationSymbol} );
/// this method is used to generate a specific math task from a specific type.
static MathOperationTask generateMathTask( MathOperation type ){
var random = Random();
var firstMember = random.nextInt(10);// 0..9
var secondMember = random.nextInt(10);
switch(type){
case MathOperation.SUM:
return MathOperationTask(
firstMember: firstMember,
secondMember: secondMember,
results: (firstMember + secondMember),
operationSymbol: PLUS
);
case MathOperation.SUBTRACTION:
var results;
if (firstMember < secondMember) {
// we exchange the values position in operation...
var temp = firstMember;
firstMember = secondMember;
secondMember = temp;
}
results = firstMember - secondMember;
return MathOperationTask(
results: results,
secondMember: secondMember,
firstMember: firstMember,
operationSymbol: LESS,
);
default:
break;
}
//in case of invalid operation...
return MathOperationTask(
firstMember: 0,
secondMember: 0,
results: 0,
);
}
}
/// A simple custom text field that limits his text
/// with a specific characters number
///
class CustomTextField extends StatelessWidget {
final maxLength;
final _text;
CustomTextField({this.maxLength = 7, String text}) :
_text = (text.length > maxLength) ? text.substring(0, maxLength ) : text;
/// this lines solves characters numbers problem
///if the text contains more characters that is allowed (maxLength) then we
/// cut the string form character 0 until last position allowed (maxLength).
#override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(top: 40.0, left: 20.0, right: 20.0),
child: Container(
height: 60.0,
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(15.0)),
child: Center(
child: Text(
_text,
style: TextStyle(
color: Colors.black,
fontSize: 48.0,
fontWeight: FontWeight.bold),
),
),
),
);
}
}

Flutter exception caught by widgets library failed assertion

I am getting below exception. I am just learning Flutter.
Below is my code:
import 'package:flutter/material.dart';
void main() => runApp(new FriendlyChatApp());
const String _name = "Hammad Tariq";
class FriendlyChatApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return new MaterialApp(
title: "Friendly Chat",
home: new ChatScreen(),
);
}
}
class ChatScreen extends StatelessWidget {
ChatScreen({this.text});
final String text;
#override
Widget build(BuildContext context) {
return new Container(
margin: const EdgeInsets.symmetric(vertical: 10.0),
child: new Row(
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
new Container(
margin: const EdgeInsets.only(right: 10.0),
child: new CircleAvatar(
child: new Text(_name),
),
),
new Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
new Text(_name, style: Theme.of(context).textTheme.subhead),
new Container(
margin: const EdgeInsets.only(top: 5.0),
child: new Text(text),
),
],
)
],
),
);
/*return new Scaffold(
appBar: AppBar(
title: new Text("Chat App"),
),
);*/
}
}
The issue is in the line
child: new Text(text)
where String text is null.
You've defined text as an optional parameter and you are not passing it from FriendlyChatApp.
If you require some inputs from parent page for the child to work properly then you can define it with #required annotation because you won't miss it accidentally.

Can you change the height of an ExpansionTile in Flutter?

The ExpansionTile inherits from the ListTile, which has a fixed height. There are no input args for tile height.
I've tried wrapping the ExpansionTile in a Container widget with a hardcoded height, but that causes the children widgets to only take up the space within the hardcoded height. Currently, because the contents in the title widget are large, I have a "Column overflowed by 23 pixels" message.
Is there any way to change an Expansion Tile's height? Or is there another Widget I could use that has the expansion/accordion feature?
I would probably copy ExpansionTile and make your own version. Sizing ListTile is easy with a Container or SizedBox, but ExpansionTile is a material widget and it doesn't look like it was built with your use case in mind.
You might want to try this package : configurable_expansion_tile
Example app :
import 'package:flutter/material.dart';
import 'package:configurable_expansion_tile/configurable_expansion_tile.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Configurable Expansion Tile Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Configurable Expansion Tile Demo'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
ConfigurableExpansionTile(
borderColorStart: Colors.blue,
borderColorEnd: Colors.orange,
animatedWidgetFollowingHeader: const Icon(
Icons.expand_more,
color: const Color(0xFF707070),
),
headerExpanded:
Flexible(child: Center(child: Text("A Header Changed"))),
header: Container(
color: Colors.transparent,
child: Center(child: Text("A Header"))),
headerBackgroundColorStart: Colors.grey,
expandedBackgroundColor: Colors.amber,
headerBackgroundColorEnd: Colors.teal,
children: [
Row(
children: <Widget>[Text("CHILD 1")],
),
Row(
children: <Widget>[Text("CHILD 2")],
)
],
)
],
),
),
);
}
}
It should get you the results you wanted.
Hope it helps,
Thanks
wrap the 'ExpansionTile' inside a 'Container' and set the margin
Container(
margin: EdgeInsets.only(right: .5.sw),
decoration: BoxDecoration(
color: AppColor.profileBoarderColor,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: AppColor.profileBoarderColor)
),
child: ExpansionTile(
title: AppTextView(text: 'Seeson 01',),
children: List.generate(10, (index) {
return SizedBox(
width: 200,
child: ListTile(title: AppTextView(text: 'Seeson 01',),));
}
),
)
This is a workaround: you can use title of the ExpansionTile widget to render the entire content instead of using leading or trailing. You can add padding to title widget to increase height of the ExpansionTile.