I want to take user input from the textfield widget
and assign in title
variable as in this code
import 'package:flutter/material.dart';
class AddTaskScreen extends StatelessWidget {
final Function callBack; // function
AddTaskScreen({required this.callBack});
@override
Widget build(BuildContext context) {
String title; // declaring the variable
return Container(
height: 350,
color: Color(0xff757575),
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(20),
topLeft: Radius.circular(20),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.lightBlueAccent,
fontSize: 24,
),
),
SizedBox(
height: 20,
),
TextField(
textAlign: TextAlign.center,
autofocus: false,
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
onChanged: (value) {
title = value; // taking the user input
},
decoration: InputDecoration(
focusColor: Colors.lightBlueAccent,
hintText: 'Type a Task',
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
),
SizedBox(
height: 20,
),
TextButton(
onPressed: () {
callBack(title); // error
},
style: TextButton.styleFrom(
backgroundColor: Colors.lightBlueAccent,
),
child: Text(
'Add',
style: TextStyle(
color: Colors.white,
fontSize: 18,
),
),
),
],
),
),
);
}
}
as you can see there is a function callBack
variable. it has the String
parameter when I pass title
in this function it gives me a warning.
here is the code for the callBack when will send this information.
import 'package:flutter/material.dart';
import 'package:todoey/models/Task.dart';
import 'package:todoey/screens/add_task_screen.dart';
import 'package:todoey/screens/bottom_section.dart';
import 'package:todoey/screens/top_section.dart';
class TasksScreen extends StatefulWidget {
@override
State<TasksScreen> createState() => _TasksScreenState();
}
class _TasksScreenState extends State<TasksScreen> {
List<Task> tasks = [];
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) => SingleChildScrollView(
child: Container(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: AddTaskScreen(
callBack: (String taskTitle) {
setState(() {
print(taskTitle);
tasks.add(
Task(
name: taskTitle,
),
);
});
Navigator.pop(context);
},
).build(context),
),
),
);
},
child: Icon(
Icons.add,
color: Colors.white,
size: 35,
),
elevation: 5,
backgroundColor: Colors.lightBlueAccent,
),
backgroundColor: Colors.lightBlueAccent,
body: SafeArea(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TopSection(),
SizedBox(
height: 30,
),
BottomSection(tasks: tasks),
],
),
),
);
}
}
for the main class, here is the code.
import 'package:flutter/material.dart';
import 'package:todoey/screens/task_screen.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: TasksScreen(),
);
}
}
In flutter, you want to store mutable objects (such as your title
) in a State
. This is because the build function can theoretically be called many times, you have no control over it. Therefore, storing the variable in the State
of an object allows you to keep it "alive" while build
is called many times.
Here is your example, adapted to work as intended:
import 'package:flutter/material.dart';
class AddTaskScreen extends StatefulWidget {
final Function callBack; // function
AddTaskScreen({required this.callBack});
@override
State<AddTaskScreen> createState() => _AddTaskScreenState();
}
class _AddTaskScreenState extends State<AddTaskScreen> {
/// Declare title in the state, so that its a long lived object
var title = ""; // Initialize it (likely as empty)
@override
Widget build(BuildContext context) {
return Container(
height: 350,
color: Color(0xff757575),
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(20),
topLeft: Radius.circular(20),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.lightBlueAccent,
fontSize: 24,
),
),
SizedBox(
height: 20,
),
TextField(
textAlign: TextAlign.center,
autofocus: false,
style: TextStyle(
color: Colors.black,
fontSize: 15,
),
onChanged: (value) {
title = value; // taking the user input
},
decoration: InputDecoration(
focusColor: Colors.lightBlueAccent,
hintText: 'Type a Task',
hintStyle: TextStyle(
color: Colors.grey,
fontSize: 12,
),
),
),
SizedBox(
height: 20,
),
TextButton(
onPressed: () {
widget.callBack(title); // error
},
style: TextButton.styleFrom(
backgroundColor: Colors.lightBlueAccent,
),
child: Text(
'Add',
style: TextStyle(
color: Colors.white,
fontSize: 18,
),
),
),
],
),
),
);
}
}