Flutter. A way for TextField to detect tap outside - flutter

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

Related

How to move AppBar when Keyboard is opened?

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) => {},
)),
}

flutter textfield with tags overflow issue

I am trying to create a textfield in which on text change I render a list of items if I click on any of the item I am adding it in front of textfield but if I add multiple tags it gives overflow error I want to increase the size of textfiled vertically. Here is the piece of code :
///TEXTFIELD
SliverToBoxAdapter(
child: Container(
margin: EdgeInsets.symmetric(horizontal: 10),
decoration: BoxDecoration(
border: Border(
bottom: BorderSide(
color: AppColor.medGrey, width: 1.5))),
child: Row(
children: [
Obx(
() => symptomsController.addedSymptoms.isEmpty
? Container()
: Container(
padding:
EdgeInsets.symmetric(horizontal: 10),
child: Wrap(
runAlignment: WrapAlignment.start,
crossAxisAlignment:
WrapCrossAlignment.start,
spacing: 3.0,
children: List.generate(
symptomsController
.addedSymptoms.length,
(index) => Container(
padding: EdgeInsets.all(10),
decoration: BoxDecoration(
borderRadius:
BorderRadius.circular(20),
color: Colors.brown
.withOpacity(0.95)),
margin: EdgeInsets.symmetric(
vertical: 2),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
///SYMPTOM NAME
Container(
child: Text(
"${symptomsController.addedSymptoms[index].commonName}",
overflow: TextOverflow
.ellipsis,
maxLines: 1,
style: AppTextStyle
.h6Bright),
),
///SPACE
SizedBox(
width: 4,
),
InkWell(
onTap: () {
symptomsController
.searchedList
.add(symptomsController
.addedSymptoms[
index]);
symptomsController
.addedSymptoms
.removeAt(index);
},
child: Icon(
Icons
.remove_circle_outline,
color: Colors.white,
size: 16,
),
)
],
),
),
),
),
),
),
),
Expanded(
child: TextField(
controller:
symptomsController.searchQuery.value,
cursorColor: AppColor.highMedGrey,
onChanged: (String query) {
symptomsController.searchString.value =
query;
},
onSubmitted: (String query) {
if (symptomsController
.searchQuery.value.text.length ==
0) {
///CLEAR LIST OF SYMPTOMS
// symptomsController.searchedList.clear();
return;
} else {
///CLEAR PREVIOUS LIST OF SYMPTOMS
symptomsController.searchedList.clear();
///START LOADING
symptomsController.loading.value = true;
///SEARCH
symptomsController.searchSymptom();
}
},
textInputAction: TextInputAction.search,
style: AppTextStyle.h4,
maxLines: 1,
maxLength: 25,
decoration: InputDecoration(
border: InputBorder.none,
counterText: "",
hintText: "Search",
hintStyle: AppTextStyle.h4,
)),
),
],
)),
),
Something like added image.. I want to increase the size vertically...Thanks in advance
Have you tried increasing the maximum row name for the TextField(). Make sur for it

ShowModalBottomSheet containing Textfield gets hidden with keyboard following Flutter upgrade 2.2.0

In my app, when user clicks on FAB, it triggers a ModalBottomSheet which contains a textfield. Up until today (when I updated to flutter 2.2.0), the code below worked fine : when user tapped the textfield, the BottomSheet moved up and we could use the keyboard fine.
Now, when we tap the textfield, the keyboard hides the BottomSheet.
Has there been a change with the update ?
Here is the code :
floatingActionButton: FloatingActionButton(
backgroundColor: Colors.blue[800],
child: Icon(Icons.add),
onPressed: () {
showModalBottomSheet<void>(
isScrollControlled: true,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20.0),
topRight: Radius.circular(20.0),
),
),
context: context,
builder: (BuildContext context) {
return Container(
height: 250,
child: Center(
child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Padding(
padding: const EdgeInsets.all(26.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
'Ajouter une liste au carnet',
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.blue[800],
fontSize: 22.0,
),
),
),
SizedBox(
height: 30,
),
Column(
children: [
TextFormField(
keyboardType: TextInputType.emailAddress,
decoration: InputDecoration(
focusColor: Colors.blue,
border: OutlineInputBorder(
borderRadius:
BorderRadius.circular(10.0),
),
labelText:
'Titre de la nouvelle liste'),
onChanged: (value) {
titre = value;
},
),
I found a way to solve this :
I added SingleChildScrollView as the first Child to ModalBottomSheet and added the padding element given by "CbL" directly there and not to the container.
return SingleChildScrollView(
padding: EdgeInsets.only(
bottom: MediaQuery.of(context).viewInsets.bottom),
child: Container(
height: 250,
Thanks CbL for your help :)
I solved this problem using a LayoutBuilder and AnimatedPadding.
because LayoutBuilder make update the MediaQuery.of(context).viewInsets.bottom(using your context) when keyboard rise up
Exemple:
showModalBottomSheet(
context: context,
isScrollControlled:true,
isDismissible: true,
builder: (_) {
return LayoutBuilder(
builder: (context, _) { //<----- very important use this context
return AnimatedPadding(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
duration: Duration(milliseconds: 150),
curve: Curves.easeOut,
child: Container(
constraints: BoxConstraints(
maxHeight: 500,
minHeight: 150
),
child: ...,
)
);
}
);
});
You can add the bottom view insets to the bottom of the bottom sheet which add the keyboard height to the padding avoiding hide of keyboard.
eg.
return Container(
padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
height: 250,
child: Center(...

Placing the cursor at the top left of a vertically stretched TextField?

I'm trying to make a page through which the user can create a note for my Notes app. This is my build method so far:
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add Note"),
actions: <Widget>[
FlatButton(
child: Icon(
Icons.save,
color: Colors.white,
),
)
],
),
body: Center(
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
TextField (
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: "Title",
),
textCapitalization: TextCapitalization.words,
),
SizedBox(
height: 16,
),
Expanded(
child: Container(
child: TextField (
expands: true,
maxLines: 25,
decoration: InputDecoration(
border: OutlineInputBorder(),
),
),
),
)
],
),
),
)
);
}
This is how the page looks right now. How do I ensure that the cursor of the second TextField is placed at the top left and make said TextField stretch to fit the remaining height?
You should set the textAlign property of the TextField to start
textAlign: start
Edit:
based on #Andy_519's and community input please use the following
textAlignVertical: top

Flutter TextFormField text hidded on overflow

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