why am i getting a null value out of this callback? - flutter

I'm trying to move the value of newTaskText from the second class to the first one , I have a callback
which is addTaskCallback in the second class that i use when i press the flat button to move the value up to the first one which is TasksScreen but when i try to print the value it comes out as null , any idea why ?
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:todoey/widgets/tasks_list.dart';
import 'add_task_screen.dart';
import 'package:todoey/models/task.dart';
class TasksScreen extends StatefulWidget {
#override
_TasksScreenState createState() => _TasksScreenState();
}
class _TasksScreenState extends State<TasksScreen> {
List<Task> tasks = [
Task(name: 'Buy Milk'),
Task(name: 'Buy eggs'),
Task(name: 'Buy bread'),
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.lightBlueAccent,
//backgroundColor: Colors.lightBlueAccent,
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.lightBlueAccent,
//backgroundColor: Colors.lightBlueAccent,
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) => AddTaskScreen(
(newTaskText) {
print(newTaskText);
},
),
);
},
child: Icon(Icons.add),
),
body: SafeArea(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(
top: 60.0, bottom: 30.0, right: 30.0, left: 30.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
CircleAvatar(
backgroundColor: Colors.white,
radius: 30.0,
child: Icon(
Icons.list,
color: Colors.lightBlueAccent,
size: 30.0,
),
),
SizedBox(height: 10.0),
Text(
'Todoey',
style: TextStyle(
color: Colors.white,
fontWeight: FontWeight.w700,
fontSize: 50.0,
),
),
Text(
'12 tasks',
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
),
),
],
),
),
Expanded(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: TasksList(tasks),
),
),
],
),
),
);
}
}
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
import 'package:todoey/models/task.dart';
class AddTaskScreen extends StatelessWidget {
final Function addTaskCallback;
AddTaskScreen(this.addTaskCallback);
#override
Widget build(BuildContext context) {
String newTaskTitle;
return Container(
color: Color(0xff757575),
child: Container(
padding: EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.lightBlueAccent,
fontSize: 30.0,
),
),
TextField(
autofocus: true,
textAlign: TextAlign.center,
onChanged: (newText) {
newTaskTitle = newText;
},
),
SizedBox(
height: 10.0,
),
FlatButton(
color: Colors.lightBlueAccent,
onPressed: () {
addTaskCallback(newTaskTitle);
print(newTaskTitle);
},
child: Text(
'Add',
style: TextStyle(
color: Colors.white,
),
),
)
],
),
),
);
}
}

Your problem here is that you defined the var newTaskTitle in the build method. Moving it out from the build method should fix your problem !
There is nothing wrong with your implementation of the callback. The only thing that could be improved is to define the Type of the variable sent in the callback Function with
final Function(String) addTaskCallback;
You could also use a TextController instead of a var updated in the onChanged method.
import 'package:flutter/material.dart';
import 'package:flutter/painting.dart';
class AddTaskScreen extends StatefulWidget {
final Function(String) addTaskCallback;
AddTaskScreen(this.addTaskCallback);
#override
_AddTaskScreenState createState() => _AddTaskScreenState();
}
class _AddTaskScreenState extends State<AddTaskScreen> {
TextEditingController textController = new TextEditingController();
#override
Widget build(BuildContext context) {
return Container(
color: Color(0xff757575),
child: Container(
padding: EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30.0),
topRight: Radius.circular(30.0),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.lightBlueAccent,
fontSize: 30.0,
),
),
TextField(
autofocus: true,
controller: textController,
textAlign: TextAlign.center,
),
SizedBox(
height: 10.0,
),
FlatButton(
color: Colors.lightBlueAccent,
onPressed: () {
widget.addTaskCallback(textController.text);
print(textController.text);
},
child: Text(
'Add',
style: TextStyle(
color: Colors.white,
),
),
)
],
),
),
);
}
}
Have fun with Flutter !

Related

Error: Non-nullable variable 'newTaskTitle' must be assigned before it can be used

tasks_screen.dart
import 'package:flutter/material.dart';
import 'package:todoey_app/widgets/tasks_list.dart';
import 'package:todoey_app/screens/add_task_screen.dart';
import 'package:todoey_app/models/task.dart';
class TasksScreen extends StatefulWidget {
#override
State<TasksScreen> createState() => _TasksScreenState();
}
class _TasksScreenState extends State<TasksScreen> {
List<Task> tasks = [
Task(name: 'Buy milk'),
Task(name: 'Buy eggs'),
Task(name: 'Buy bread'),
];
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.lightBlueAccent,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () {
showModalBottomSheet(
context: context,
builder: (context) => AddTaskScreen(
(newTaskTitle) {
// print(newTaskTitle);
setState(() {
tasks.add(Task(name: newTaskTitle));
});
Navigator.pop(context);
},
),
);
},
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Container(
padding: EdgeInsets.only(
top: 60.0, left: 30.0, right: 30.0, bottom: 30.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
CircleAvatar(
child: Icon(
Icons.list,
size: 30.0,
color: Colors.lightBlueAccent,
),
backgroundColor: Colors.white,
radius: 30.0,
),
SizedBox(
height: 10.0,
),
Text(
'Todoey',
style: TextStyle(
color: Colors.white,
fontSize: 50.0,
fontWeight: FontWeight.w700,
),
),
Text(
'${tasks.length} Tasks',
style: TextStyle(
color: Colors.white,
fontSize: 18.0,
),
),
],
),
),
Expanded(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topRight: Radius.circular(20.0),
topLeft: Radius.circular(20.0),
)),
child: TasksList(tasks),
),
),
],
),
);
}
}
add_task_screen.dart
import 'package:flutter/material.dart';
class AddTaskScreen extends StatelessWidget {
final Function addTaskCallback;
AddTaskScreen(this.addTaskCallback);
#override
Widget build(BuildContext context) {
// String? newTaskTitle;
// String newTaskTitle = '';
String newTaskTitle = "It's Working";
// String newTaskTitle;
return Container(
color: Color(0xff757575),
child: Container(
padding: EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.lightBlueAccent,
fontSize: 30.0,
),
),
TextField(
autofocus: true,
textAlign: TextAlign.center,
onChanged: (newText) {
// print(newText);
newTaskTitle = newText;
},
),
TextButton(
onPressed: () {
print(newTaskTitle);
addTaskCallback(newTaskTitle);
},
child: Text(
'Add',
style: TextStyle(color: Colors.white),
),
style: TextButton.styleFrom(
backgroundColor: Colors.lightBlueAccent,
),
)
],
),
),
);
}
}
I have initialized newTaskTitle but when i type new text in my TextField and try to add it to my Task list but instead of taking the new value that's comming from textField it only takes the value that I have initialized at the beginning which is newTaskTitle = "It's Working";.
How can i solve it?
You can use ValueSetter for this.
Example:
import 'package:flutter/material.dart';
class AddTaskScreen extends StatelessWidget {
//final Function addTaskCallback;
final ValueSetter<String> onChanged; //THIS LINE
AddTaskScreen(this.onChanged);
#override
Widget build(BuildContext context) {
// String? newTaskTitle;
// String newTaskTitle = '';
String newTaskTitle = "It's Working";
// String newTaskTitle;
return Container(
color: Color(0xff757575),
child: Container(
padding: EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
)),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.lightBlueAccent,
fontSize: 30.0,
),
),
TextField(
autofocus: true,
textAlign: TextAlign.center,
onChanged: (newText) {
// print(newText);
newTaskTitle = newText;
},
),
TextButton(
onPressed: () {
print(newTaskTitle);
onChanged(newTaskTitle); //THIS LINE
},
child: Text(
'Add',
style: TextStyle(color: Colors.white),
),
style: TextButton.styleFrom(
backgroundColor: Colors.lightBlueAccent,
),
)
],
),
),
);
}
}

How to set the size of Text field Button

I am building a Flutter application where I am trying to build simple login UI but having problem as shown in image below. One problem is the size of the email field and the password field is different and another is login button is being overflowed by 13-pixels? Also want to set the height underscore of Forget your password. How can It be solved? Thank you in advance.
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
const MyApp({super.key});
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Navigation Bar',
theme: ThemeData(
primaryColor: Color(0xFFC41A3B),
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
#override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
var _isVisible = false;
#override
Widget build(BuildContext context) {
return Scaffold(
body: SingleChildScrollView(
child: Container(
constraints: BoxConstraints(
maxHeight: MediaQuery.of(context).size.height,
),
decoration: BoxDecoration(
gradient: LinearGradient(
colors: const [
Colors.blue,
],
begin: Alignment.topLeft,
end: Alignment.centerRight,
),
),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
flex: 2,
child: Padding(
padding: const EdgeInsets.symmetric(
vertical: 36.0,
horizontal: 24.0,
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
crossAxisAlignment: CrossAxisAlignment.start,
children: const [
Text(
'Login',
style: TextStyle(
color: Colors.white,
fontSize: 46.0,
fontWeight: FontWeight.w800,
),
),
SizedBox(
height: 10.0,
),
Text(
'Enter to the butiful world',
style: TextStyle(
color: Colors.white,
fontSize: 22.0,
fontWeight: FontWeight.w300,
),
),
],
),
),
),
Expanded(
flex: 2,
child: Container(
width: double.infinity,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(30),
topRight: Radius.circular(30),
),
),
child: Padding(
padding: const EdgeInsets.all(24.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
TextField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
borderSide: BorderSide(
width: 0,
style: BorderStyle.none,
),
),
filled: true,
fillColor: Color(0xffe73ded),
hintText: "E-mail",
prefixIcon: Icon(
Icons.email,
color: Colors.grey,
),
)),
SizedBox(
height: 20.0,
),
TextField(
obscureText: _isVisible ? false :true,
keyboardType: TextInputType.visiblePassword,
decoration: InputDecoration(
suffix: IconButton(
onPressed: () {
setState(() {
_isVisible = !_isVisible;
});
},
icon: Icon(
_isVisible ? Icons.visibility : Icons.visibility_off,
color: Colors.grey,
),
),
border: OutlineInputBorder(
borderRadius: BorderRadius.all(
Radius.circular(10.0),
),
borderSide: BorderSide(
width: 0,
style: BorderStyle.none,
),
),
filled: true,
fillColor: Color(0xffe73ded),
hintText: "Password",
prefixIcon: Icon(
Icons.lock_rounded,
color: Colors.grey,
),
)),
SizedBox(
height: 5.0,
),
Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
TextButton(
onPressed: () {},
child: Text(
'Forgot your password',
style: TextStyle(
color: Colors.blue,
decoration: TextDecoration.underline,
),
),
),
],
),
SizedBox(
height: 20.0,
),
Container(
color: Colors.blue,
width: double.infinity,
child: ElevatedButton(
onPressed: () {},
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(28),
),
),
child: Padding(
padding:
const EdgeInsets.symmetric(vertical: 16.0),
child: Text(
'Login',
style: TextStyle(
color: Colors.white,
fontSize: 16.0,
),
),
),
),
),
SizedBox( height: 2,),
RichText(
text: TextSpan(
text: 'Do you have an account?',
style: TextStyle(
color: Colors.black,
fontSize: 18,
),
children: [
TextSpan(
text: 'Register',
style: TextStyle(
color: Colors.blue,
fontSize: 18,
),
recognizer: TapGestureRecognizer()
..onTap = () {}),
],
),
),
],
),
),
),
),
],
),
),
),
);
}
}
The issue is you created a container with max height as the device.then used expanded widgets which are equally spaced. You can try increasing the flex value of the second expanded widget
Expanded(
flex: 3
)
Now the first and second expanded will be of ratio 2:3 which will give more space to the second widget

Flutter textfield is not updating another variable

I have the following widget.
import 'package:flutter/material.dart';
class AddTaskScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
String? newTaskTitle;
return Container(
color: Color(0xFF757575),
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 30,
color: Colors.lightBlueAccent,
),
),
TextField(
autofocus: true,
textAlign: TextAlign.center,
onChanged: (String newText) {
newTaskTitle = newText;
},
),
FlatButton(
child: Text(
'Add',
style: TextStyle(
color: Colors.white,
),
),
color: Colors.lightBlueAccent,
onPressed: () {
// this line prints null
// even though I typed something in my textfield
print(newTaskTitle);
},
)
],
),
),
);
}
}
Here I am updating my textfield value with the variable newTaskTitle. It successfully updates when the text value changes. But when I click on the add button, it prints the newTaskTitle as null. I even print it inside the onChanged of textfield, and it was getting the updated value. But it is not getting the updated value inside the onPressed function of the add button. How do I get the updated value and what am I doing wrong here?
That is because you have a stateless widget with a String? newTaskTitle;
which is null by default and doesn't get updated. Try this instead:
import 'package:flutter/material.dart';
class AddTaskScreen extends StatelfulWidget {
//your constructor here
#override
_AddTaskScreenState createState() => _AddTaskScreenState();
}
class _AddTaskScreenState extends State<AddTaskScreen>{
String? newTaskTitle;
#override
Widget build(BuildContext context) {
return Container(
color: Color(0xFF757575),
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 30,
color: Colors.lightBlueAccent,
),
),
TextField(
autofocus: true,
textAlign: TextAlign.center,
onChanged: (String newText) {
setState((){
newTaskTitle = newText;
});
},
),
FlatButton(
child: Text(
'Add',
style: TextStyle(
color: Colors.white,
),
),
color: Colors.lightBlueAccent,
onPressed: () {
// this line prints null
// even though I typed something in my textfield
print(newTaskTitle);
},
)
],
),
),
);
}
}
User TextEditingController and pass _nameController.text.
import 'package:flutter/material.dart';
class AddTaskScreen extends StatelessWidget {
TextEditingController _nameController = TextEditingController();
#override
Widget build(BuildContext context) {
String? newTaskTitle;
return Container(
color: Color(0xFF757575),
child: Container(
padding: EdgeInsets.all(20),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 30,
color: Colors.lightBlueAccent,
),
),
TextField(
controller: _nameController,
autofocus: true,
textAlign: TextAlign.center,
onChanged: (String newText) {
newTaskTitle = newText;
},
),
FlatButton(
child: Text(
'Add',
style: TextStyle(
color: Colors.white,
),
),
color: Colors.lightBlueAccent,
onPressed: () {
// this line prints null
// even though I typed something in my textfield
print(_nameController.text);
},
)
],
),
),
);
}
}

Row error set<container> can't be assigned to the list type 'Widget'

The if(...) {...} else {...} condition is not working in Row widget.
I have tried wrapping it with a Container, that didn't work nor did calling them as a function. I want the if condition to be executed when widget.sp is not equal to null. But I am not understanding the error.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
class Product_Card extends StatefulWidget {
const Product_Card({Key key, this.imagefile, this.productname,this.productdetails,this.mrp,this.sp,this.currencie,this.quantity,this.unit}) : super(key: key);
final PickedFile imagefile;
final String productname;
final String currencie;
final String mrp;
final String sp;
final String quantity;
final String unit;
final String productdetails;
#override
_Product_CardState createState() => _Product_CardState();
}
class _Product_CardState extends State<Product_Card> {
bool addproduct ;
int _counter=1;
#override
void initState() {
super.initState();
addproduct = false;
}
void _incrementCounter() {
setState(() {
_counter++;
});
}
void _decrementCounter() {
setState(() {
_counter--;
});
}
#override
Widget build(BuildContext context) {
return Container(
height: 150,
padding: EdgeInsets.fromLTRB(15, 8, 15, 8),
width: MediaQuery.of(context).size.width,
child: Column(
// mainAxisAlignment: MainAxisAlignment.start,
//crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
// mainAxisAlignment: MainAxisAlignment.start,
children: <Widget>[
SizedBox(
height: 110,
width: 100,
child: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: FileImage(
File(widget.imagefile.path),
),
fit: BoxFit.contain),
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(12),
bottomLeft: Radius.circular(12),
topRight: Radius.circular(12),
bottomRight: Radius.circular(12),
)),
),
),
SizedBox(width: 10),
/*Container(
height: 120,
width: 50,
decoration: BoxDecoration(
image: DecorationImage(
image: FileImage(
File(imagefile.path),
),
fit: BoxFit.fitWidth),
),
),*/
Expanded(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisAlignment: MainAxisAlignment.center,
children: [
//productname (),
Text(
widget.productname ,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
Padding(
padding: const EdgeInsets.only(top: 10),
child: Text("${widget.quantity} ${widget.unit}",
style: TextStyle(
fontSize: 15,
),
),
),
Container(
height: 30,
width: MediaQuery.of(context).size.width-120,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if(widget.sp!=null)
Container(
child: RichText(text: TextSpan(children: [
TextSpan(
text: '${widget.currencie}${widget.sp}',
style: TextStyle(fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black),
),
TextSpan(
text: '${widget.currencie}${widget.mrp}',
style: TextStyle(fontSize: 15,
fontWeight: FontWeight.normal,
decoration: TextDecoration.lineThrough,
color: Colors.black54),
),
])),
)
else
Text("${widget.currencie}${widget.mrp}" ,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Container(child: addproduct?addmore():add())
],
),
),
],
),
)
],
),
],
),
);
}
Widget addButton() {
return InkWell(
onTap: () { },
child: Center(
child: Container(
height: 20,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(4), color: Colors.blueAccent,
),
child: Center(
child: Text(
"ADD +",
style: TextStyle(
color: Colors.white, fontSize: 16),
)),
),
),
);
}
Widget spprice(){
RichText(text:
TextSpan(children: [
TextSpan(
text: '${widget.currencie}${widget.sp}',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold,color: Colors.black),
),
TextSpan(
text: '${widget.currencie}${widget.mrp}',
style: TextStyle(fontSize: 24, fontWeight: FontWeight.normal,decoration: TextDecoration.lineThrough, color: Colors.black54),
),
])
);
}
Widget mrpprice(){
Container(
child: Text("${widget.currencie}${widget.mrp}" ,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,color: Colors.black
),
),
);
}
Widget add(){
return Container(
height: 20,
child: OutlineButton(
onPressed: (){
setState(() {
addproduct=true;
});
},
borderSide: BorderSide(color: Colors.blue),
//color: Colors.blueAccent,
//disabledBorderColor: Colors.blueAccent,
child: Text("ADD +",style: TextStyle(color: Colors.blue, fontSize: 16,fontWeight: FontWeight.normal),
)
),
);
}
Widget productname(){
Wrap(
children: [
Text(
widget.productname ,
style: TextStyle(
fontWeight: FontWeight.bold,
fontSize: 20,
),
),
],
);
}
Widget addmore(){
return Container(
decoration: BoxDecoration(
border: Border.all(color: Colors.blue),
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4),
bottomLeft: Radius.circular(4),
topRight: Radius.circular(4),
bottomRight: Radius.circular(4),
),
),
child: Row(
children: [
InkWell(
onTap: (){
if(_counter==1) {
setState(() {
addproduct=false;
});
}
else{
_decrementCounter();
}
},
child: Container(
height: 18,
width: 25,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(4),
bottomLeft: Radius.circular(4),
),
//border: Border.all(color: Colors.blueAccent),
shape: BoxShape.rectangle, color: Colors.white
),
child: Center(
child: Text("-", style: TextStyle(
color: Colors.blueAccent, fontSize: 16, fontWeight: FontWeight.bold),),
),
),
),
Container(
height: 18,
width: 25,
child: Center(
child: Text("$_counter", style: TextStyle(
color: Colors.blueAccent, fontSize: 16,),),
),
),
InkWell(
onTap: (){
if(_counter<=99){
_incrementCounter();
}
},
child: Container(
height: 18,
width: 25,
decoration: BoxDecoration(
borderRadius: BorderRadius.only(
topRight: Radius.circular(4),
bottomRight: Radius.circular(4),
),
shape: BoxShape.rectangle, color: Colors.white
),
child: Center(
child: Text("+" , style: TextStyle(
color: Colors.blueAccent, fontSize: 16, fontWeight: FontWeight.bold),),
),
),
)
],
),
);
}
}
Image result
selling price text form field
'''
Widget spTextField() {
return Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
keyboardType: TextInputType.number,
inputFormatters: [
FilteringTextInputFormatter.allow(RegExp("[0-9\.]")),
CurrencyFormat()
],
controller: _sp,
validator: (value) {
if (value.length > 7) {
return "Enter less than 1000000";
}
return null;
},
decoration: InputDecoration(
labelText: "Selling Price",
),
maxLines: null,
),
);
}
'''
There is no if() {...} else {...} available in the Widget Tree. Instead, use a ternary operation 'sp != null ? Container(...) : Container(...)
I'm not sure what Container(child: addproduct ? addmore() : add()) does.
I suppose addproduct is a bool flag and both addmore() and add() return a Widget (probably a button) which is fine.
Add more detail to your question if you need more help.
You can copy paste run full code below
In this case to use if else you can remove {} and comma before else
In working demo, first widget sp is null and second widget is string
code snippet
Test(
sp: null,
currencie: 1.0,
mrp: 2.0,
),
Test(
sp: "string",
currencie: 1.0,
mrp: 2.0,
)
...
children: [
if (widget.sp != null)
Container(
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: '${widget.currencie}${widget.sp}',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black),
),
TextSpan(
text: '${widget.currencie}${widget.mrp}',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.normal,
decoration: TextDecoration.lineThrough,
color: Colors.black54),
),
],
),
),
)
else
Text(
"${widget.currencie}${widget.mrp}",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
working demo
full code
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Test(
sp: null,
currencie: 1.0,
mrp: 2.0,
),
Test(
sp: "string",
currencie: 1.0,
mrp: 2.0,
)
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
),
);
}
}
class Test extends StatefulWidget {
String sp;
double currencie;
double mrp;
Test({this.sp, this.currencie, this.mrp});
#override
_TestState createState() => _TestState();
}
class _TestState extends State<Test> {
bool addproduct = true;
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: [
if (widget.sp != null)
Container(
child: RichText(
text: TextSpan(
children: [
TextSpan(
text: '${widget.currencie}${widget.sp}',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: Colors.black),
),
TextSpan(
text: '${widget.currencie}${widget.mrp}',
style: TextStyle(
fontSize: 15,
fontWeight: FontWeight.normal,
decoration: TextDecoration.lineThrough,
color: Colors.black54),
),
],
),
),
)
else
Text(
"${widget.currencie}${widget.mrp}",
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Container(child: addproduct ? Text("addmore()") : Text("add()"))
//Container(child: addproduct ? addmore() : add())
],
);
}
}

How to fix ' FlatButton hidden behind the keyboard'?

I Have a widget showModalBottomSheet .. inside it has a class (AddTaskScreen),
But FlatButton hidden behind the keyboard .. What should I do to make it visible?
this is code :
class AddTaskScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
String newTaskTitle;
return Container(
padding: EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 30.0,
color: Colors.lightBlueAccent,
fontWeight: FontWeight.w700),
),
TextField(
autofocus: true,
textAlign: TextAlign.center,
onChanged: (newText) {
newTaskTitle = newText;
},
),
FlatButton(
child: Text(
'Add',
style: TextStyle(color: Colors.white),
),
color: Colors.lightBlueAccent,
onPressed: () {
Provider.of<TaskData>(context).addTask(newTaskTitle);
Navigator.pop(context);
},
)
],
),
);
}
}
i tried this solution but doesn't work :
Padding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: FlatButton()
)
this is image ScreenShot of my App
You can trigger bottom sheet using this code
void openBottomSheet(context) {
showModalBottomSheet<dynamic>(
context: context,
builder: (BuildContext context) {
return Padding(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Wrap(
children: <Widget>[
AddTaskScreen(),
],
),
);
},
);
}
make sure we wrap AddTaskScreen with Wrap so it will efficiently rendered.
and we also wrap it with Padding and its value of viewInsets.bottom
this is the full code
import 'package:flutter/material.dart';
class AddTaskScreen extends StatelessWidget {
#override
Widget build(BuildContext context) {
String newTaskTitle;
return Container(
padding: EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 30.0,
color: Colors.lightBlueAccent,
fontWeight: FontWeight.w700),
),
TextField(
autofocus: false,
textAlign: TextAlign.center,
onChanged: (newText) {
newTaskTitle = newText;
},
),
FlatButton(
child: Text(
'Add',
style: TextStyle(color: Colors.white),
),
color: Colors.lightBlueAccent,
onPressed: () {
Navigator.pop(context);
},
)
],
),
);
}
}
class ButtomSheetScreen extends StatelessWidget {
void openBottomSheet(context) {
showModalBottomSheet<dynamic>(
context: context,
builder: (BuildContext context) {
return Padding(
padding:
EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: Wrap(
children: <Widget>[
AddTaskScreen(),
],
),
);
},
);
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"Bottom Sheet",
),
leading: Builder(
builder: (BuildContext context) {
return IconButton(
icon: const Icon(Icons.chat_bubble_outline),
onPressed: () {
openBottomSheet(context);
},
);
},
),
),
body: Container(),
);
}
}
Here is the repo of example working-app.
Wrap you container in SingleChildScrollView() widget. By this, user can scroll to view the button.
return SingleChildScrollView(
child: Container(
Wrap the Container in a ListViewBuilder so that the button can be scrolled up/down. I think I got the parenthesis correct below:
return ( ListView.builder(
itemCount: 1,
itemBuilder: (context, index) {
return ( Container(
padding: EdgeInsets.all(20.0),
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Text(
'Add Task',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 30.0,
color: Colors.lightBlueAccent,
fontWeight: FontWeight.w700),
),
TextField(
autofocus: true,
textAlign: TextAlign.center,
onChanged: (newText) {
newTaskTitle = newText;
},
),
FlatButton(
child: Text(
'Add',
style: TextStyle(color: Colors.white),
),
color: Colors.lightBlueAccent,
onPressed: () {
Provider.of<TaskData>(context).addTask(newTaskTitle);
Navigator.pop(context);
},
)
],
),
) );
}));