So my app looks like this:
Now, when I click the TextField in the BottomAppBar, I see this:
Code:
bottomNavigationBar: Container(
decoration: BoxDecoration(
color: Colors.blue[50],
borderRadius: BorderRadius.all(Radius.circular(20))),
padding: EdgeInsets.all(12.0),
child: TextField(
decoration: InputDecoration(hintText: 'Add a new item'),
onSubmitted: (str) => {},
)),
I want the BottomAppBar to move up when I type so I can see what I'm typing. How do I go about doing this?
I would personally suggest not using the bottomnavigationbar, which is meant to disappear under a keyboard, but instead just use a bottom-aligned view in the body of your scaffold. This will automatically move up when the keyboard appears. If you put the ListView and the Container with the textfield into a column and wrap the ListView in an Expanded widget, it should work pretty easily:
Column(
children: [
Expanded(child: ListView(...)), // your item list
Container(...), // your textfield
]
)
You should try with stack
Stack(
children: [
SingleChildScrollView(
---------
),
Align(
alignment: Alignment.bottomCenter,
child: Container(
decoration: BoxDecoration(
color: Colors.blue[50],
borderRadius: BorderRadius.all(Radius.circular(20))),
padding: EdgeInsets.all(12.0),
child: TextField(
decoration: InputDecoration(hintText: 'Add a new item'),
onSubmitted: (str) => {},
)),
),
],
)
Add this to your Container in the bottomNavigationBar property:
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
),
Or to keep the padding you already added:
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom,
).add(
const EdgeInsets.all(12.0),
),
What #fravolt suggested is right in the sense that bottomnavigationbar should not move as per Material Design.
In my case I moved the widget up using the Translate widget:
Widget build(BuildContext context) {
final mediaQueryData = MediaQuery.of(context);
Transform.translate(
offset: Offset(
0.0,
-1 * mediaQueryData.viewInsets.bottom,
),
child: Container(
decoration: BoxDecoration(
color: Colors.blue[50],
borderRadius: BorderRadius.all(Radius.circular(20))),
padding: EdgeInsets.all(12.0),
child: TextField(
decoration: InputDecoration(hintText: 'Add a new item'),
onSubmitted: (str) => {},
)),
}
Related
I am trying to create a chat screen with text field at the bottom and whenever it is clicked the keyboard comes up and the textfield should be on top of the keyboard but my own isn't doing what it's supposed to do. I have checked other similar questions and answers on google, stackoverflow and github but it still stays the maybe because in mine am using constraints: BoxConstraints(maxHeight: 160), which might be what is causing it but i don't really know
This my code
class _ChatSectionState
extends State<ChatSectionState> {
List<File> images = List<File>();
getMultiFile() async {
await pickFileFromMobile("multi").then((value) {
if (value != null) {
value.paths.forEach((element) {
images.add(File(element));
});
// images = value.paths.map((path) => File(path)).toList();
}
});
setState(() {});
}
#override
Widget build(BuildContext context) {
return SafeArea(
child: Scaffold(
appBar: AppBar(...,
body: Container(
height: double.infinity,
child: Stack(
children: [
Padding(
padding: EdgeInsets.only(bottom: 50),
child: Container(
child: ListView.builder(
itemCount: 10,
reverse: true,
shrinkWrap: true,
physics: ScrollPhysics(),
itemBuilder: (ctx, idx) {...
///...
),
),
),
///This is the part that hides behide the keyboard when it appears which i want to show on top
Align(
alignment: Alignment.bottomCenter,
child: Container(
decoration: BoxDecoration(
color: white,
border: Border(
top: BorderSide(
color: grey[400],
width: .7,
),
bottom: BorderSide(
color: grey[400],
width: .7,
)),
),
constraints: BoxConstraints(maxHeight: 160), //This is the box contraints
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: [
(images.length < 1)
? SizedBox(height: 0)
: Expanded(
child: ListView.builder(
shrinkWrap: true,
scrollDirection: Axis.horizontal,
physics: ScrollPhysics(),
padding: EdgeInsets.symmetric(
vertical: 7, horizontal: 10),
itemCount: images.length,
itemBuilder: (ctx, idx) {
return Container(
///... This is to show a image from file width a height of 100
);
},
),
),
Container(
decoration: BoxDecoration(
border: Border(
top: BorderSide(
color: grey[300],
width: .5,
)),
),
child: Row(children: [
Container(
margin: new EdgeInsets.symmetric(horizontal: 8.0),
child: new IconButton(
icon: new Icon(Icons.image),
onPressed: () => getMultiFile(),
color: primary,
),
),
Flexible(
child: Container(
child: TextFormField(
//controller: messageEditingController,
style: TextStyle(color: nBlack, fontSize: 15.0),
decoration: InputDecoration.collapsed(
hintText: 'Type a message',
hintStyle: TextStyle(color: grey),
),
onFieldSubmitted: (value) {},
),
),
),
Container(
margin: new EdgeInsets.symmetric(horizontal: 8.0),
child: new IconButton(
icon: new Icon(Icons.send),
onPressed: () {},
color: primary,
),
),
]),
),
],
),
),
)
],
),
),
resizeToAvoidBottomInset: false,
));
}
}
Please how can I make it work cause i have checked different pages still does give me what i want. I also tried this [answer][1]
[1]: https://stackoverflow.com/a/49715952/14650702 which worked but the animation was terrible
You can change resizeToAvoidBottomInset: ture, for scaffold.
it will shrink the whole scaffold when keyboard is opened.
I use another way. resizeToAvoidBottomInset: true and do some changes for lifting widgets top of keyboard.
bottom = MediaQuery.of(context).viewInsets.bottom;
Scaffold(
resizeToAvoidBottomInset: ture,
body: SingleChildScrollView(
reverse:true,
child: Padding(
padding: EdgeInsets.only(bottom: bottom),
child: ...
)));
if you decrease space from keyboard to last widget use MediaQuery.of(context).viewInsets.bottom/2 e.x.
I want to make this kind of input field.
I found a flutter_chip_input package in pubdev that already serve this functionality but it was kinda buggy. I have no time to wait for the next update of the plugin so I decided to move on and build it my self.
In web app, I can easily achieve this design using relative-absolute property in css and some javascript.
Yes, I already tried using Stack widget, but the problem is the Container (a wrapper of the white list in the bottom of the input field) won't stick to the bottom.
Whenever more content is loaded, the height grows to the top instead of going to the bottom, causing the input field to be hidden below the container.
I only need to know about how to make the list stick to the bottom of the input field and make the height grows to the bottom. I'll take care the rest of it.
Any clue? Please have a look at my current script:
#override
Widget build(BuildContext context) {
return Stack(
alignment: AlignmentDirectional.bottomCenter,
overflow: Overflow.visible,
children: [
TextFormField(
focusNode: _focusNode,
decoration: widget.decoration,
onChanged: (String query) {
print(query);
},
),
Positioned(
bottom: -30,
left: 0,
right: 0,
child: Container(
height: 100,
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(20),
),
child: Text('asdasdasd'),
),
),
],
);
}
Thanks in advance!
You can use OverlayEntry to make it float and CompositeTransformTarget and CompositeTransformFollower combined with LayerLink so the list will stick to the bottom of input.
You can read this article for example implementation
Flutter: Using Overlay to display floating widgets
Try using a searchDelegate widget if you're okay with it occupying the full screen. It's quite simple to use.
Docs here: https://api.flutter.dev/flutter/material/SearchDelegate-class.html
EDIT: My bad, it is not necessary to use it in the appBar. Call
showSearch(context: context, delegate: SearchDel()); from anywhere. It takes up the full screen tho.
If not, I'll have to add the code for the widget. Thought of some ways to make it.
How About This? without Stack juga bisa kok
Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
IntrinsicWidth(
child: Container(
constraints: BoxConstraints(
minWidth: 200,
),
child: TextFormField(
onChanged: (String query) {
print(query);
},
),
),
),
Container(
constraints: BoxConstraints(
minHeight: 100,
),
child: Column(
children: [
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(8),
),
child: Text('asdasdasd'),
),
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(8),
),
child: Text('asdasdasd'),
),
Container(
padding: EdgeInsets.all(12),
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(8),
),
child: Text('asdasdasd'),
),
]
),
),
],
),
Here I'm taking two widgets one is textfield widget and another one is Icon widget both are placed in seperate container. I'm very new to flutter, I dont know how to place two widgets parallely each other with different size. But somehow designed for my mobile but when i run my app on different mobile its widgets are overflowing.Can anybody help me out from this issue. Thanks in advance!!! For More reference see the image given.
Here is my code
Padding(
padding: const EdgeInsets.only(
top: 10.0, bottom: 4.0, right: 20.0, left: 20.0),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceAround,
children: <Widget>[
Container(
child: Material(
color: Colors.white,
elevation: 3.0,
// CONTAINER BACKSIDE SHADOW DEPTH
borderRadius: BorderRadius.circular(5.0),
shadowColor: Color(0xFF90A4AE),
//CONTAINER BACKSIDE SHADOW COLOR
child: Expanded(
child: TextField(
decoration: InputDecoration(
border: InputBorder.none,
prefixIcon: IconButton(
icon: Icon(
Icons.search,
color: Colors.pink,
),
onPressed: () {},
),
hintText: "Search for restaurant",
hintStyle: TextStyle(fontSize: 15),
),
onChanged: (input) {
print(input);
},
),
),
),
height: 55.0,
width: MediaQuery
.of(context)
.size
.width - 120,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 1.0,
style: BorderStyle.solid),
borderRadius: BorderRadius.circular(5.0),
),
),
Container(
child: Material(
color: Colors.white,
elevation: 3.0,
// CONTAINER BACKSIDE SHADOW DEPTH
borderRadius: BorderRadius.circular(5.0),
shadowColor: Color(
0xFF90A4AE),
child: IconButton(
icon: Icon(Icons.tune),
color: Colors.pink,
onPressed: () {
[enter image description here][1]
},
), //CONTAINER BACKSIDE SHADOW COLOR
),
height: 55.0,
width: MediaQuery
.of(context)
.size
.width - 300,
decoration: BoxDecoration(
border: Border.all(
color: Colors.white,
width: 1.0,
style: BorderStyle.solid),
borderRadius: BorderRadius.circular(5.0)),
)
],
),
),
From the screenshot and the code, I see there are two widgets in a row and the screen is overflown as it couldn't accommodate and show both of them.
There are two solutions:
To show the row children in the next line automatically if overflown.
To make the row children scrollable row-wise.
NOTE: SMLink is my custom widget. Just used here for demonstration purposes.
SOLUTION-1
The simple workaround would be to use the Wrap widget instead of the Row widget.
The Wrap widget simply takes the children who are prone to screen overflow and places them on the next line. You can set the direction, spacing etc, in addition to the options that Row widget can offer. Try it & let me know.
// By default, it behaves as Row, you can set the direction attribute to Axi.vertical to mimic the Column widget.
Wrap(
spacing: 8.0,
runAlignment: WrapAlignment.center,
crossAxisAlignment: WrapCrossAlignment.center,
alignment: WrapAlignment.center,
children:
[
SMLink(logo: 'Medium', link: Constants.LINK_MEDIUM),
SMLink(logo: 'linkedin', link: Constants.LINK_LINKEDIN),
SMLink(logo: 'facebook', link: Constants.LINK_FAEBOOK),
SMLink(logo: 'Qwiklabs', link: Constants.LINK_QWIKLABS),
],
)
SOLUTION-2
From the screenshot, the other way to fix would be by making the row scrollable. This makes UI look consistent in your case. We can use ListView widget for this.
ListView(
scrollDirection: Axis.horizontal,
children:
[
SMLink(logo: 'Medium', link: Constants.LINK_MEDIUM),
SMLink(logo: 'linkedin', link: Constants.LINK_LINKEDIN),
SMLink(logo: 'facebook', link: Constants.LINK_FAEBOOK),
SMLink(logo: 'Qwiklabs', link: Constants.LINK_QWIKLABS),
],
)
When I reach the limit of the TextFormField the text disapear...
I tryed multiple config but still not working, I dont find why.
Dialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(6.0)), //this right here
child: Container(
height: 400.0,
child: Column(children: <Widget>[
Expanded(
child: new Align(
alignment: FractionalOffset.center,
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Icon(Icons.account_circle, color: Colors.blue),
Text('Test')
])),
),
Expanded(
child: new Padding(
padding: EdgeInsets.only(left: 10, right: 10, top: 10),
child: new Align(
alignment: FractionalOffset.centerLeft,
child: TextFormField(
initialValue: _inputs[0],
onChanged: (text) {
_inputs[0] = text;
checkOkEnabled();
},
autocorrect: false,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Mme / M',
hintText: 'test'))),
)),]))))
Same problem on two device :
And Error field get hidded on strange way too.
The Expanded is in a Container with a height of 400.
You are reducing the height of TextFormField from its actual height to something lesser. It happens normally because of additional padding. try to identify that and remove
in InputDecoration, add isDense: true and contentPadding: EdgeInsets.zero
Is there any way to detect a tap outside of TextTield?
I wanna make a self sufficient search field component which should expend when focused and shrink when a focus is lost.
The TextField is using FocusNode to unfocus itself when the focus is not needed but the problem is that I can't get the way to detect a tap outside of it. Wrapping the whole app in GestureDetector and requesting a new focus on tap is not an option at all because, first this tap can be easily intercepted by any component containing their own gesture detectors, second it will make my component not self sufficient and I'll have to write some extra code outside of it, which is not preferable
here is the code of my search field for the moment
#override
Widget build(BuildContext context) {
return Row(
mainAxisAlignment: MainAxisAlignment.end,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(_padding),
child: AnimatedContainer(
decoration: BoxDecoration(
border: Border.all(color: Colors.black12, width: 2),
borderRadius: BorderRadius.all(Radius.circular(6)),
color: pizzaWhite,
),
height: 40,
width: !_isExpanded
? MediaQuery.of(context).size.width / 2 - (_padding * 2)
: MediaQuery.of(context).size.width - (_padding * 2),
child: Padding(
padding: const EdgeInsets.only(left: _padding, right: _padding),
child: Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Expanded(
child: RawKeyboardListener(
focusNode: _keyboardFocusNode,
onKey: (RawKeyEvent e) {
},
child: TextField(
keyboardType: TextInputType.text,
onEditingComplete: _sendSearch,
controller: _controller,
focusNode: _textFocusNode,
cursorColor: pizzaBottomBarColor,
onTap: () => _switchExpanded(true),
decoration: InputDecoration(
alignLabelWithHint: true,
contentPadding: EdgeInsets.only(top: 1),
border: InputBorder.none,
hintText: 'Search...'
),
style: TextStyle(
fontSize: 18,
fontFamily: 'OpenSans',
fontWeight: FontWeight.w100,
),
),
),
),
GestureDetector(
onTap: () => _switchExpanded(false),
child: Icon(
Icons.search
),
),
],
),
),
duration: Duration(milliseconds: 250),
curve: Curves.fastOutSlowIn,
),
)
],
);
}
I've removed the solution code from here (as it's outdated) and added my pub repository which contains the most recent solution
https://pub.dev/packages/flutter_focus_watcher
You can also filnd it on my github
https://github.com/caseyryan/flutter_focus_watcher
you need to separate from the other widgets and wrap them in GestureDetector and call it's onTap | onTapDown