What is the best way to show a widget after an action? In my case, I want to show the Text Forgot Password? after the user misses the login credentials so he get's the option for reset password or to be sent his password through email.
Picture1:
And the second picture after the user missed the password, an action triggers and the Forgot Password appears:
I've thought of using AnimatedOpacity() but not sure if this is the right approach. Thanks in advance for the advice.
This is a minimal working code, that delivers the message. You can use setState.
in your stateful widget.
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
TextEditingController _email = TextEditingController();
TextEditingController _password = TextEditingController();
bool _forgotPassword = false;
#override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: _email,
),
TextField(
controller: _password,
),
_forgotPassword
? TextButton(
onPressed: () async {
//await your logic for forgotton password
},
child: Text('Forgot Password'))
: Container(),
TextButton(
onPressed: () async {
//await your login logic, if it returns false\error\not authenticated, then you can change the state of _forgotPassword, and then shows 'forgot password TextButton'
setState(() {
_forgotPassword = true;
});
},
child: Text('Login'))
],
);
}
}
You can use state management to show or hide any widget on any action. See the example below, read the explanation in the inline comment.
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget{
#override
Widget build(BuildContext context) {
return MaterialApp(
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget{
#override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool showcard = false; //set widget show to false
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title:Text("Show widget on action"), //title of app
backgroundColor: Colors.redAccent, //background color of app bar
),
body: Container(
child: Column(children: [
showcard?Container( //check if showcard is true or false
child: Card(
child: Padding(
padding: EdgeInsets.all(20),
child:Text("This is card widget")
)
)
):Container(),
//if showcard is true then show card, else show empty contianer.
Container(
child: ElevatedButton(
child: Text(showcard?"Hide Card":"Show Card"),
onPressed: (){
setState(() { //update UI with setState
if(showcard){
showcard = false;
//if showcard is true, then make it false to hide
}else{
showcard = true;
//if showcard is false, then make it true to show.
}
});
},
)
)
],)
)
);
}
}
In this example, there is raised button, when you click on it, the card will appear, and there will be "hide" button, and when you click on it, the card will disappear, or vice versa.
Output:
Card widget after pressing "show card" button.
Here's a very simple code sample on how to do it using the Visibility widget.
import 'package:flutter/material.dart';
class LoginScreen extends StatefulWidget {
#override
_LoginScreenState createState() => _LoginScreenState();
}
class _LoginScreenState extends State<LoginScreen> {
TextEditingController emailController = TextEditingController();
TextEditingController passwordController = TextEditingController();
bool showForgotPassword = false;
#override
Widget build(BuildContext context) {
return Column(
children: [
TextField(
controller: emailController,
),
TextField(
controller: passwordController,
),
Visibility(
child: Text("Forgot Password?"),
visible: showForgotPassword,
),
RaisedButton(
child: Text("Log in"),
onPressed: () {
// Validate password
if (passwordController.text != 'realpassword') {
setState(() {
showForgotPassword = true;
});
} else {
// continue
}
},
),
],
);
}
}
When we click the login button with the wrong password. We change the visible property of the Visibility widget to true. Hence, the password text becomes visible.
If we type the correct password, then the visible property of the Visibility widget becomes false. Hence, the text becomes invisible.
OUTPUT
When they put the wrong password:
When they put the correct password:
Related
I've a dropdown on my screen, which I want to close every time the user minimises the app (Pause State). I looked into the DropDownButton widget, and it seems it uses Navigator.push() method, so ideally it should be dismissed with Navigator.pop(), if I'm not wrong.
Here is what I've tried already -
Use global key to get the context of dropdown widget and implement Navigator.pop(key.currentContext) inside didChangeAppLifecycleState() function.
Use focusNode to implement .unfocus() to remove the focus from the dropdown.
Maintain a isDropdownDialogOpen boolean which I set to true on onTap() and false on onChange(). And then simple pop() if its true on app minimisation. But this approach fails when the user opens the dropdown and then closes it by tapping outside the dropdown dialog. I can't set the boolean to false in that case.
My requirement is that - I've to dismiss the dropdown whenever the user minimises the app, if it was open in the first place.
I've gone through bunch of SO questions and GitHub comments, that are even remotely similar, but couldn't find anything helpful.
Loose Code -
class Auth extends State<Authentication> with WidgetsBindingObserver {
bool isDropdownOpen = false;
GlobalKey _dropdownKey = GlobalKey();
FocusNode _focusNode;
#override
void initState() {
WidgetsBinding.instance.addObserver(this);
super.initState();
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
// To pop the open dropdown dialog whenever app is minimised (and opened back on again)
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
switch (state) {
case AppLifecycleState.resumed:
if(isDropdownOpen)
pop();
// Also tried pop(_dropdownKey.currentContext)
break;
case AppLifecycleState.paused:
break;
case AppLifecycleState.inactive:
break;
case AppLifecycleState.detached:
break;
}
}
build() {
return Scaffold(
// Dummy Dropdown button with random values
body: DropdownButton(
key: _dropdownKey,
focusNode: _focusNode,
value: "one",
items: ["one", "two", "three", "four", "five"],
//boolean values changing fine, but when user taps outside the dropdown dialog, dropdown is closed and neither of onChanged() and onTap() is called. Need a call back (or something similar) for this particular case.
onChange(value) => isDropdownOpen = false;
onTap() => isDropdownOpen = ! isDropdownOpen;
)
);
}
}
For your ref - https://github.com/flutter/flutter/issues/87989
Does this work for you?
import 'package:flutter/material.dart';
void main() async {
runApp(
MyApp(),
);
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: Home(),
);
}
}
class Home extends StatefulWidget {
const Home({Key key}) : super(key: key);
#override
_HomeState createState() => _HomeState();
}
class _HomeState extends State<Home> with WidgetsBindingObserver {
#override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
#override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
AppLifecycleState currentAppLifecycleState;
bool isDropdownMenuShown = false;
#override
void didChangeAppLifecycleState(AppLifecycleState state) {
setState(
() => currentAppLifecycleState = state,
);
}
String value;
#override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((_) {
if (<AppLifecycleState>[
AppLifecycleState.inactive,
AppLifecycleState.detached,
AppLifecycleState.paused,
].contains(currentAppLifecycleState) &&
isDropdownMenuShown) {
print('Closing dropdown');
Navigator.pop(context);
}
});
return Scaffold(
appBar: AppBar(
title: const Text('Flutter Demo'),
),
body: Center(
child: GestureDetector(
onLongPressStart: (LongPressStartDetails details) async {
final left = details.globalPosition.dx;
final top = details.globalPosition.dy;
setState(() => isDropdownMenuShown = true);
final value = await showMenu<String>(
context: context,
position: RelativeRect.fromLTRB(left, top, left, top),
items: <PopupMenuEntry<String>>[
PopupMenuItem(
child: const Text('Option 1'),
value: 'Option 1',
),
PopupMenuItem(
child: const Text('Option 2'),
value: 'Option 2',
),
PopupMenuItem(
child: const Text('Option 3'),
value: 'Option 3',
),
],
);
setState(() => isDropdownMenuShown = false);
if (value == null) return;
print('You chose: $value');
},
child: InkWell(
onTap: () {},
child: Container(
alignment: Alignment.center,
child: Text(
'Long press to show dropdown',
textAlign: TextAlign.center,
),
),
),
),
),
);
}
}
How does it work?
We keep track of the current app state using the didChangeAppLifecycleState method.
Whenever the dropdown is shown the isDropdownMenuShown variable is set to true.
Whenever the dropdown is closed/exited the variable is set to false.
We add a post frame callback (it is called after each rebuild) and we check if the app went into background and if the dropdown is shown. If yes, the dropdown is closed.
You could use FocusManager.instance.primaryFocus?.unfocus();
This is my screen with TextField and Button. When someone clicks on show button, I want it to show the name below the button as shown in below picture.
Code below:
class Demo extends StatefulWidget {
#override
_DemoState createState() => _DemoState();
}
class _DemoState extends State<Demo> {
final name = TextEditingController();
#override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Column(
children: [
Row(
children: [
Text(
'Name'
),
TextField(
controller: name,
)
],
),
RaisedButton(
onPressed: (){
},
child: Text('Show'),
)
],
),
),
);
}
}
This can be a basic example for your question. The UI is not exactly what you've shown above
class Question extends StatefulWidget {
Question({Key key}) : super(key: key);
#override
_QuestionState createState() => _QuestionState();
}
class _QuestionState extends State<Question> {
String text = '';
bool shouldDisplay = false;
#override
Widget build(BuildContext context) {
return Column(
children: [
Center(
child: TextField(
onChanged: (value) {
setState(() {
text = value;
});
},
),
),
FlatButton(onPressed: () {
setState(() {
shouldDisplay = !shouldDisplay;
});
}, child: Text('Submit')),
shouldDisplay ? Text(text) : Spacer()
],
);
}
}
Hope this helps.
Initialize two variables. One for a TextEditingController and one for the text value.
TextEditingController controller = TextEditingController();
String display = '';
Give your TextField a controller.
TextField(controller:controller);
In your button, set onPressed to change display text to the controller text.
FlatButton(
child: Text("Show"),
onPressed()=> setState((){display = controller.text;});
),
Then where you want to show the text, set the text string to display.
Text(display);
I would advice you to learn the basics of flutter first before asking these kinds of questions. This can be simply achieved through using TextEditingController and setState(). Simply define a controller for your TextField and then call setState() when your button is pressed. Note that you have to be on a StatefulWidget since calling setState() rebuilds the UI.
Create a TextEditingController and string above the #override Widget build:
String displayName="";
final myController = TextEditingController();
Create a TextField and add assign the controller to it:
TextField(
controller: myController,
);
Call setState() on button pressed:
MaterialButton(
child: Text("Show"),
onPressed: (){
setState(() {
displayName=myController.text;
});
})
Display it using a Text widget:
Text(displayName);
Good Luck!
You can find out how to use TextEditingController here: https://flutter.dev/docs/cookbook/forms/retrieve-input
More about widgets here: https://www.youtube.com/playlist?list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG
I have built a home screen with is rendering cards using ListView.builder. These cards have a confirm button which fetches the confirmation status from firestore. When I tap on the confirm button, a bottom sheet appears asking whether I am sure. Once I tap Yes on the bottom sheet, I want the card on homepage to be rebuilt and change the button from confirm to confirm.
I used the setState to change the value at the onPressed event and it is successfully changing it but, the confirm button is not changing to confirmed.
Any leads on how to solve this issue would be really appreciated.
Homepage cards layout
class HomepageCards extends StatefulWidget {
final FirebaseUser user;
final Map cardDetails;
HomepageCards({#required this.user, this.cardDetails});
#override
_HomepageCardsState createState() => _HomepageCardsState();
}
class _HomepageCardsState extends State<HomepageCards> {
#override
Widget build(BuildContext context) {
// Confirmation status from firebase about the captain
bool isConfirmed = widget.cardDetails['c'];
final screenHeight = MediaQuery.of(context).size.height;
final screenWidth = MediaQuery.of(context).size.width;
return SingleChildScrollView(
padding: EdgeInsets.fromLTRB(screenHeight / 60, screenHeight / 90,
// UI Code here......
Container(
height: screenHeight / 80,
),
// Confirm Button checking condition and building UI accordingly
isConfirmed == true
? captainConfirmed(context, isConfirmed) // if confirmed then different button style widget
: confirmAndCancelButton(context, isConfirmed), //if not confirmed then show confirm and cancel button in the card
],
),
// Some UI
);
}
}
Once clicking on cancel, the bottom sheet:
Widget confirmCaptainBookingBottomSheet(
BuildContext context, bool isConfirmed) {
final screenHeight = MediaQuery.of(context).size.height;
final screenWidth = MediaQuery.of(context).size.width;
showModalBottomSheet(
context: context,
builder: (context) {
return StatefulBuilder(
builder: (BuildContext context, StateSetter setState) {
return Container(
// UI Code
Text(
'Do you want to confirm?',
style: TextStyle(
color: black.color,
fontSize: headSize.fontSize,
),
),
child: FlatButton(
child: Text(
'YES',
style: TextStyle(
color: cyan.color,
fontSize: headSize.fontSize),
),
onPressed: () {
print(isConfirmed);
setState(() {
// change the value of is confirmed which is used to build different buttons in the UI as shown in the above code
isConfirmed = true;
});
print(isConfirmed);
Navigator.pop(context);
}),
),
child: FlatButton(
child: Text(
'NO',
style: TextStyle(
color: cyan.color,
fontSize: headSize.fontSize),
),
onPressed: () {
Navigator.pop(context);
}),
),
});
}
You can create a function in _HomepageCardsState class which change state of isConfirmed and pass that function to widget where you want change the state. Then on onPressed of yes just give that function. it will change state of isConfirmed in _HomepageCardsState widget so you can see captainConfirmed widget.
I am leaving small demo which simulates how you can do that in your case.
I hope following code clear your idea.
class DeleteWidget extends StatefulWidget {
#override
_DeleteWidgetState createState() => _DeleteWidgetState();
}
class _DeleteWidgetState extends State<DeleteWidget> {
bool isConfirmed = false;
changeconfirmed() {
setState(() {
isConfirmed = !isConfirmed;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Container(
child: Center(
child: isConfirmed
? Home1()
: Home2(
function: changeconfirmed,
),
)),
);
}
}
class Home1 extends StatelessWidget {
#override
Widget build(BuildContext context) {
return Container(
child: Text("confirmed Widget"),
);
}
}
class Home2 extends StatelessWidget {
final Function function;
Home2({this.function});
#override
Widget build(BuildContext context) {
return RaisedButton(
child: Text("press"),
onPressed: function,
);
}
}
With my current code the TextField becomes focused, but the cursor and keyboard aren't triggered (requires a second tap). I believe this is because the TextField doesn't exist when the focus node is initially focused, but I'm struggling to find a solution.
Here is a simple recreation of the problem based on a Cookbook recipe:
class MyCustomForm extends StatefulWidget {
#override
_MyCustomFormState createState() => _MyCustomFormState();
}
class _MyCustomFormState extends State<MyCustomForm> {
FocusNode myFocusNode;
bool _editingField2 = false;
#override
void initState() {
super.initState();
myFocusNode = FocusNode();
myFocusNode.addListener(_focusListener);
}
#override
void dispose() {
myFocusNode.dispose();
super.dispose();
}
// Set _editingField2 to true when focusNode has focus.
_focusListener() {
if (myFocusNode.hasFocus) {
setState(() {
_editingField2 = true;
});
} else {
setState(() {
_editingField2 = false;
});
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Text Field Focus'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// The first text field is focused on as soon as the app starts.
TextField(
autofocus: true,
),
// The second text field is created when _editingField2 (after FAB press).
_editingField2
? TextField(
focusNode: myFocusNode,
)
: Text('ayy'),
],
),
),
floatingActionButton: FloatingActionButton(
// Give focus node focus on FAB press.
onPressed: () => FocusScope.of(context).requestFocus(myFocusNode),
tooltip: 'Focus Second Text Field',
child: Icon(Icons.edit),
),
);
}
}
Here is my code, with important bits commented.
class TaskListItem extends StatefulWidget {
final Task task;
TaskListItem({#required this.task});
#override
State createState() => _TaskListItemState();
}
class _TaskListItemState extends State<TaskListItem> {
bool _isEditing;
FocusNode _focusNode;
final TextEditingController _textEditingController = TextEditingController();
#override
initState() {
super.initState();
_isEditing = false;
_textEditingController.text = widget.task.text;
_textEditingController.addListener(_handleTextFieldUpdate);
_focusNode = FocusNode(debugLabel: 'TaskListItem');
_focusNode.addListener(_handleFocusChange);
}
#override
void dispose() {
_focusNode.removeListener(_handleFocusChange);
_focusNode.dispose();
_textEditingController.dispose();
super.dispose();
}
_handleTextFieldUpdate() {
Provider.of<TaskListModel>(context, listen: false)
.updateTaskText(widget.task, _textEditingController.text);
}
// Update state to determine if Text or TextField widget is created in build().
_handleFocusChange() {
if (_focusNode.hasFocus) {
setState(() {
_isEditing = true;
});
} else {
setState(() {
_isEditing = false;
});
}
}
Widget _buildTitle() {
return Row(
children: <Widget>[
Expanded(
// Create either TextField or Text based on _isEditing value.
child: _isEditing && !widget.task.isComplete
? TextField(
focusNode: _focusNode,
controller: _textEditingController,
)
: Text(
widget.task.text,
style: widget.task.isComplete
? TextStyle(decoration: TextDecoration.lineThrough)
: null,
),
),
],
);
}
#override
Widget build(BuildContext context) {
return ListTile(
leading: Checkbox(
value: widget.task.isComplete,
//Dismiss focus when box is checked
onChanged: (bool checked) {
_focusNode.unfocus();
Provider.of<TaskListModel>(context, listen: false)
.toggleComplete(widget.task);
},
),
title: _buildTitle(),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => Provider.of<TaskListModel>(context, listen: false)
.deleteTask(widget.task),
),
onTap: () {
// I'm requesting focus here, but the Textfield doesn't exist yet?
FocusScope.of(context).requestFocus(_focusNode);
print('tapped');
},
);
}
}
What you have to do is change focus inside build, you're trying to change focus before the screen has done rebuilding that widget already. try this please, using your own code.
I'm not sure if you needed to really listen to that focus change or if you only wanted to accomplish the focus change after enabling the widget, if you do want to listen for the focus change let me know.
class MyCustomForm extends StatefulWidget {
#override
_MyCustomFormState createState() => _MyCustomFormState();
}
class _MyCustomFormState extends State<MyCustomForm> {
FocusNode myFocusNode = FocusNode();
bool _editingField2 = false;
#override
void dispose() {
myFocusNode?.dispose();
super.dispose();
}
#override
Widget build(BuildContext context) {
//here you do the focus request
if (_editingField2) {
FocusScope.of(context).requestFocus(myFocusNode);
}
return Scaffold(
appBar: AppBar(
title: Text('Text Field Focus'),
),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// The first text field is focused on as soon as the app starts.
TextField(
autofocus: true,
),
// The second text field is created when _editingField2 (after FAB press).
_editingField2
? TextField(
focusNode: myFocusNode,
)
: Text('ayy'),
],
),
),
floatingActionButton: FloatingActionButton(
// Give focus node focus on FAB press.
onPressed: () {
setState(() {
_editingField2 = true;
});
},
tooltip: 'Focus Second Text Field',
child: Icon(Icons.edit),
),
);
}
}
I'm developping a Flutter App that needed to have a form. So when the user open the app, a Splash Screen appear before the form that have the following code :
import 'package:flutter/material.dart';
import '../model/User.dart';
import './FileManager.dart';
import './MyListPage.dart';
class UserLoader extends StatefulWidget {
#override
_UserLoaderState createState() => new _UserLoaderState();
}
class _UserLoaderState extends State<UserLoader> {
final userFileName = "user_infos.txt";
User _user;
#override
Widget build(BuildContext context) {
print("build UserLoader");
final _formKey = new GlobalKey<FormState>();
final _firstNameController = new TextEditingController();
final _lastNameController = new TextEditingController();
final _emailController = new TextEditingController();
final _phoneController = new TextEditingController();
return new Scaffold(
appBar: new AppBar(
title: new Text("Informations"),
actions: <Widget>[
new IconButton(
icon: const Icon(Icons.save),
onPressed: () {
_user = _onFormValidate(
_formKey.currentState,
_firstNameController.text,
_lastNameController.text,
_emailController.text,
_phoneController.text);
})
],
),
body: new Center(
child: new SingleChildScrollView(
child: new Form(
key: _formKey,
child: new Column(children: <Widget>[
new ListTile(
leading: const Icon(Icons.person),
title: new TextFormField(
decoration: new InputDecoration(
hintText: "Prénom",
),
keyboardType: TextInputType.text,
controller: _firstNameController,
validator: _validateName,
),
),
new ListTile(
leading: const Icon(Icons.person),
title: new TextFormField(
decoration: new InputDecoration(
hintText: "Nom",
),
keyboardType: TextInputType.text,
controller: _lastNameController,
validator: _validateName,
),
),
Etc, etc ...
However when i tap the TextField, the keyboard appear and close immediately and all the component is rebuild. So it is impossible for me to complete the form..
Can someone have a solution please? Thanks in advance !
You haven't given us the entire code for this, so I don't know what the context is.
One pitfall I myself have fallen into (and might be affecting you, as I gather from your description) is having a stateful widget nested inside another stateful widget.
For instance,
class Parent extends StatefulWidget {
#override
ParentState createState() => ParentState();
(...)
}
class ParentState extends State<Parent> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Child(),
);
}
(...)
}
class Child extends StatefulWidget {
#override
ChildState createState() => ChildState();
(...)
}
class ChildState extends State<Child> {
#override
Widget build(BuildContext context) {
return TextField(...);
}
(...)
}
The problem here is that a rebuild of Parent means that ParentState().build() is run, and a new Child instance is created, with a new ChildState object. Which resets everything.
Try not recreating ChildWidget, but instead saving it on ParentState, like so:
class Parent extends StatefulWidget {
#override
ParentState createState() => ParentState();
(...)
}
class ParentState extends State<Parent> {
Child _child;
#override
void initState() {
_child = Child();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: _child,
);
}
(...)
}
// The rest remains the same
Edit: You just need to remember that, if your widget tree is a bit more complex, you may need to 1) pass a callback from the Parent to notify of state changes, and 2) not forget to also call setState() on the Child.
you just need make a new class and import that on your target class that seen problem. for example :
I usually create a class like this :
class MiddleWare
{
static MiddleWare shared = MiddleWare();
_MiddleWare(){}
String myText = "my Text";
// every variables should be here...
}
and
import "MiddleWare.dart";
class myclass extends StatefulWidget {
#override
_myclassState createState() => _myclassState();
}
class _myclassState extends State<myclass> {
#override
Widget build(BuildContext context) {
return Container(child: Text(MiddleWare.shared.myText));
}
}
that's it.
hi dont use Scaffold key i.e
Scaffold (
...
key: _scaffoldKey, //remove this
...
)
on the page and do a complete page rebuild (not hot reload), and you should be fine worked for me tho!
In my case, I have two stateful widgets, the parent and the child. I used the pushReplacement method on the parent to fix the widget reload issue when the text form field is selected in the child widget.
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => WidgetChildren(idUser:
widget.idUser)),
);
try to create a function which receives context like this
class YourPage extends StatefulWidget {
const YourPage(Key key) : super(key: key);
static Future<void> show({ BuildContext context,}) async {
await Navigator.of(context, rootNavigator: true).push(
MaterialPageRoute(
builder: (context) => YourPage()
);}
#override
_YourPageState createState() => _YourPageState();
}
......YourPage Build.....
then provide context to your page, when rebuilding it will have core context that prevents parent rebuild.
onPressed: () async {
await YourPage.show(context: context);
Move your variables (controllers and keys) from build to class-fields level.
in my case it was related to this property in Scaffold widget: 'resizeToAvoidBottomInset'
I changed it to true and problem solved.