Reputation: 1301
When i select a Textfield, the keyboard is going to be shown but the keyboard hide my selected TextField. Does someone have a solution?
Upvotes: 41
Views: 87400
Reputation: 960
A pretty short way to realize this is by simply using a MediaQuery for getting the bottom view insets. This would look as follows:
return Column(
children: <Widget>[
TextField(
decoration: InputDecoration.collapsed(hintText: "Start typing ..."),
controller: _chatController,
),
SizedBox(
height: MediaQuery.of(context).viewInsets.bottom,
),
],
);
Hope it helps!
Upvotes: 25
Reputation: 3004
Wrap with MaterialApp, it should work.
@override
Widget build(BuildContext context) {
buildContext = context;
return ScreenUtilInit(
designSize: getDeviceSize(context),
splitScreenMode: true,
builder: (BuildContext buildContext, Widget? child) {
return MaterialApp(
theme: Styles.appTheme(),
home: Container(
decoration: const BoxDecoration(
color: AppColors.backgroundColor,
),
Upvotes: 0
Reputation: 449
I had a very complex widget with Stack, Column and Single ChildChildScrollView, and I fixed it by adding a padding to the SCSV like this:
child: Stack(
children: [
Padding(
padding: const EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
child: SingleChildScrollView(
child: Column(
children: [... a lot of children here, one of them is a TextField],
),
),
),
// a widget at the bottom of the stack that shows despite the size of the scrollable column
],
),
Upvotes: 5
Reputation: 1048
Wrap your widget into Padding and set padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
Upvotes: 5
Reputation: 31
you can easily try to use Flexible widget just wrap your widget with it
Flexible(
child: Image(
image :
AssetImage('assets/logo.png'),
),
),
Upvotes: 0
Reputation: 256
It's very easy in my case check out code
Column(
children: [
Expanded(
child:// Top View,
),
postSend // edittext. and button
],
)
Upvotes: -3
Reputation: 764
I had the same problem where the parent widget is Material and the other widgets are inside a ListView. The problem was fixed when I changed the parent widget to Scaffold without any extra code and the TextField, TextFormField in my case, is being showed above the Keyboard automatically. So, if you encountered this problem just make sure to have Scaffold as the main widget.
Upvotes: 6
Reputation: 801
In my case I had to combine answer given by @Javid Noutash
which uses AnimationController
along with scrollPadding
property of TextFormField
.
code:
Add this line in build method
double bottomInsets = MediaQuery.of(context).viewInsets.bottom;
Add scrollPadding
property
return ListView(
children:[
...widgets,
Container(
margin:EdgeInsets.only(
top:1.0,
left:1.0,
right:1.0,
bottom:_focusNode.hasFocus && bottomInsets != 0?
_animation.value : 1.0),
child:TextFormField(
decoration: InputDecoration(
labelText: 'I move!',
),
focusNode: _focusNode,
scrollPadding: EdgeInsets.only(bottom:bottomInsets + 40.0),
),
),
]
);
Note: Combine this code with @Javid Noutash
's code
Upvotes: 8
Reputation: 1
Instead of TextField
, use TextFormField
and wrap the widget with a list of TextFormField
to Form
:
Form(
child: Column(
children: <Widget> [
TextFormField(),
TextFormField(),
...
TextFormField(),
]
)
)
Upvotes: 0
Reputation: 1223
var _contentController;
void _settingModalBottomSheet(BuildContext context, String initialText) {
_contentController = new TextEditingController(text: initialText);
showModalBottomSheet(
context: context,
isDismissible: true,
builder: (BuildContext bc) {
return Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Container(
height: 40,
margin: EdgeInsets.only(left: 4, right: 4, bottom: 8),
decoration: BoxDecoration(
color: AppColor.bgTextFieldComment,
borderRadius: BorderRadius.circular(16),
),
child: Row(
children: <Widget>[
Expanded(
child: Padding(
padding: EdgeInsets.only(left: 24),
child: TextField(
focusNode: _contentFocusNode,
autofocus: true,
controller: _contentController,
decoration: InputDecoration(
hintText: 'Enter Content',
border: InputBorder.none,
fillColor: AppColor.bgTextFieldComment,
),
keyboardType: TextInputType.multiline,
maxLines: null,
style: TextStyle(
color: Colors.black87,
fontSize: 16,
fontStyle: FontStyle.normal,
),
)),
),
InkWell(
child: Padding(
padding: EdgeInsets.only(left: 4, right: 4),
child: Icon(
Icons.send,
color: Colors.blue,
),
),
onTap: () {
// do ON TAP
},
),
],
),
),
SizedBox(
height: MediaQuery.of(bc).viewInsets.bottom,
),
],
);
},).then((value) {
print('Exit Modal');
});
print('request focus');
_contentFocusNode.requestFocus();
}
Upvotes: 0
Reputation: 597
The above does not work if you have a CustomScrollview
in a NestedScrollView
.
First, you need to give the TextField a focusNode.
TextField(focusNode:_focusNode(),
...);
Use NestedScrollViewState to get access to the innerScrollController
of the NestedScrollView
. You can view the example here on how to get the innerScrollController. Declare a globalKey and assign it to NestedScrollView.
body: NestedScrollView(
key: globalKey,
...)
Setup the focusNode
Listener to listen for when the textfield has been activated and animate the innerScrollController accordingly.
void initState() {
super.initState();
_focusNode.addListener(() {
if (_focusNode.hasFocus) {
double innerOffSet = globalKey.currentState.innerController.offset;
if(innerOffSet < 100)
globalKey.currentState.innerController.jumpTo(innerOffSet+100);
}
});
}
Upvotes: 0
Reputation: 51
My way here
Scaffold(
resizeToAvoidBottomInset: false,
resizeToAvoidBottomPadding: false,
body: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/Bg img.png'), fit: BoxFit.fill)),
child: Padding(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: CustomScrollView(
slivers: [
SliverFillRemaining(
hasScrollBody: false,
child: Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
.............
This template has some advantages:
Upvotes: 3
Reputation: 166
The most simple way is to just wrap it with
SingleChildScrollView( ... )
When the textfield is on the page bottom and the keyboard appears, the textfield is automatically scrolled up. Then the text may be entered right above the keyboard.
Upvotes: 3
Reputation: 484
Scaffold(
resizeToAvoidBottomInset: true,
body: SingleChildScrollView(
child: Container(
child: Column(
children: <Widget>[
TextFormField(
decoration: InputDecoration(
labelText: 'Enter Text',
),
),TextFormField(
decoration: InputDecoration(
labelText: 'Enter Text',
),
),TextFormField(
decoration: InputDecoration(
labelText: 'Enter Text',
),
),TextFormField(
decoration: InputDecoration(
labelText: 'Enter Text',
),
),TextFormField(
decoration: InputDecoration(
labelText: 'Enter Text',
),
),TextFormField(
decoration: InputDecoration(
labelText: 'Enter Text',
),
),TextFormField(
decoration: InputDecoration(
labelText: 'Enter Text',
),
),
TextFormField(
decoration: InputDecoration(
labelText: 'Enter Text',
),
)
],
),
),
)
);
// resizeToAvoidBottomPadding: false isDeprecated
use resizeToAvoidBottomInset: true.
Upvotes: 40
Reputation: 1242
<activity
android:name="..ActivityName"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize"/>
only for android if you use FlutterFragment add configChanges and windowSoftInputMode for the Activity.
another way add your TextField to a ListView
ListView(
children: <Widget>[
TextField(),
TextField(),
]
)
Upvotes: 1
Reputation: 256
Just cut and paste your body code in this -
SingleChildScrollView(
child: Stack(
children: <Widget>[
// your body code
],
),
),
Upvotes: 19
Reputation: 2252
Compose an animation and move your TextField container up when a TextField gets focus.
For learning about composing animations refer to: Composing Animations and Chaining Animations in Dart's Flutter Framework
Use Flutter's FocusNode to detect the focus on a TextField
Edit:
Here I've written an example that does exactly what you want:
import 'package:flutter/material.dart';
void main() => runApp(new MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Animation Demo',
theme: new ThemeData(
primaryColor: new Color(0xFFFF0000),
),
home: new FormDemo(),
);
}
}
class FormDemo extends StatefulWidget {
@override
_FormDemoState createState() => _FormDemoState();
}
class _FormDemoState extends State<FormDemo> with SingleTickerProviderStateMixin {
AnimationController _controller;
Animation _animation;
FocusNode _focusNode = FocusNode();
@override
void initState() {
super.initState();
_controller = AnimationController(vsync: this, duration: Duration(milliseconds: 300));
_animation = Tween(begin: 300.0, end: 50.0).animate(_controller)
..addListener(() {
setState(() {});
});
_focusNode.addListener(() {
if (_focusNode.hasFocus) {
_controller.forward();
} else {
_controller.reverse();
}
});
}
@override
void dispose() {
_controller.dispose();
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomPadding: false, // this avoids the overflow error
appBar: AppBar(
title: Text('TextField Animation Demo'),
),
body: new InkWell( // to dismiss the keyboard when the user tabs out of the TextField
splashColor: Colors.transparent,
onTap: () {
FocusScope.of(context).requestFocus(FocusNode());
},
child: Container(
padding: const EdgeInsets.all(20.0),
child: Column(
children: <Widget>[
SizedBox(height: _animation.value),
TextFormField(
decoration: InputDecoration(
labelText: 'I move!',
),
focusNode: _focusNode,
)
],
),
),
),
);
}
}
Upvotes: 31