Flutter: Conflict between TextField's onTap and prefixIcon's onPressed - flutter

When the prefixicon is clicked, onTap will be called back automatically. How to ban it?
child: TextField(
onTap: ReplyController.to.onClickTextField,
decoration: InputDecoration(
prefixIcon: IconButton(
onPressed: ReplyController.to.openEmojiField,
color: Colors.black,
icon: Icon(CupertinoIcons.smiley),
),
),
),

You can add a FocusNode to the TextField to have access whether the field is actually focused. And now if you want to ignore the onTap when textfield has focus you could modify the onTap such as onTap: !focusNode.hasFocus? ReplyController.to.onClickTextField : null

Related

onHover effect doesn't work on TextButton nor InkWell

I am developing a Flutter website. I have some links that I want to behave as a normal link: with a different color when the user hovers over them. However, I can't manage to make the color change.
I have tried using a TextButton with the onHover property. I have also tried with an Inkwell onHover property and hoverColor. I have wrapped the InkWell with Material and my onTap function is defined. I have also tried by wrapping this on an AnimatedContainer, but nothing seems to work.
Here is my code.
TextStyle? bodyTextStyle = Theme.of(context).textTheme.bodySmall;
InkWell(
color: Colors.transparent,
child: Text(
"data policy",
style: bodyTextStyle,
),
onTap: () => Navigator.of(context).pushNamed(
Navigation(context).routes["data policy"]),
onHover: (isHovering) {
setState(() {
bodyTextStyle = isHovering
? bodyTextStyle?.copyWith(
color: Theme.of(context).colorScheme.outline)
: bodyTextStyle;
});
},
),
I prefer using InkWell rather than TextButton in order to get rid of the shadow around the text that TextButton creates.
You can follow this snippet, hoverColor from InkWell can overlap.
InkWell(
child: SizedBox(
width: 100,
height: 100,
child: Text(
"Text",
style: linkTextStyle,
)),
onTap: () {},
hoverColor: Colors.transparent, //button splash color
onHover: (isHovering) {
linkTextStyle = isHovering
? TextStyle(color: Colors.red)
: TextStyle(color: Colors.cyanAccent);
setState(() {});
},
),
Also You can check MouseRegion, elevation on buttonStyle.

Flutter 2: maxLength inside the textfield without using onChanged

I am trying to find a way to use maxLength and put it inside of the textfield to have a nice rendering. However, I don't want to use the onChanged parameter because I would have to use a setState, but this not the good way to use it.
The parameter maxLength from the flutter's textfield is designed to do not update the state, so that every statefull widgets don't have to rebuild.
So I would like to put the 0/50 inside, at the end of the textfield, on the same line as Title.
From this :
To this :
So somebody have an idea of how to do it without using the parameter onChanged ?
Does flutter has implemented this functionality ?
Try with this, hope you get a solution.
TextField(
maxLength: 250,
buildCounter: (_, {currentLength, maxLength, isFocused}) => Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Container(
alignment: Alignment.centerLeft,
child: Text(currentLength.toString() + "/" + maxLength.toString())),
),
)
Also, Try with this,
TextField(
controller: nameController,
maxLength: 60,
prefixIcon: Icon(
Icons.account_circle,
color: Colors.black45,
),
),

How to make InkWell `onLongPress()` override tap on a TextField inside of it?

I have a TextField inside of an InkWell with an onLongPress() callback. The problem is, despite the fact that even when long pressing on the TextField, I see the ripple effect on InkWell, but the onLongPress() does not run after the long press time passes. It only gets me into editing Text. When pressing on the bottom side of the Card, everything runs fine.
In short: On tap I want to get into TextField editing. On long press I want to trigger the onLongPress(), not the TextField, even if I am pressing on it.
How do I do this? Thank you.
InkWell(
onLongPress: () {
// do stuff
}
child: ListTile(
title: TextField(),
),
),
You can use the AbsorbPointer widget to ignore the TextField gesture recognizer:
InkWell(
onLongPress: () {
print('onLongPress');
},
child: AbsorbPointer(
child: ListTile(
title: TextField(),
),
),
)
To still enabling the editing of TextField when single tapping on it, you can use FocusNode like this:
InkWell(
onLongPress: () {
print('onLongPress');
},
onTap: () => node.requestFocus(),
child: AbsorbPointer(
child: ListTile(
title: TextField(
focusNode: node,
controller: textController,
),
),
),
)
#Bach 's answer helped me to find a solution. Thank you!
InkWell(
onLongPress: () {
// do stuff
},
child: ListTile(
title: GestureDetector(
onTap: () => FocusScope.of(context).requestFocus(_focusNode),
child: AbsorbPointer(
child: TextField(
focusNode: _focusNode,
),
),
),
),
The only problem is now that I started messing with focusNode, multiple input fiels are focusing at the same time. But that is a whole other story ;)
UPD: Just realised, that I can't move text cursor this way. So not useful.
It seems that IntrinsicWidth widget can find the right balance between long press and text editing.
The rationale behind is that IntrinsicWidth will let the TextField shrink to its minimum width, therefore avoiding a gesture collision with the InkWell
So your solution can be like this:
InkWell(
onLongPress: () {
// do stuff
}
child: ListTile(
child: IntrinsicWidth(
title: TextField(
//remember to make some hints here
//because with intrinsicwidth if your textfield is empty it might disappear
),
),
),
),

Flutter avoid focusing on TextField when clicking button inside

I have a widget that looks like this:
The code looks like this:
TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter your address or ZIP code',
hintStyle: TextStyle(fontSize: 18),
suffixIcon: IconButton(
icon: Icon(Icons.gps_fixed),
onPressed: () {
...
},
),
),
),
The behavior I want is that when the user clicks on the GPS button, instead of having the keyboard pop up, the TextField should become temporarily read-only and be filled with the current address after we get a response from some API.
The problem is, the way I wrote the code causes the TextField to gain focus when the GPS button is clicked. The click handler then disables the TextField to do async query, which causes the keyboard to disappear immediately. This creates a very janky animation.
Is there a way to make the TextField NOT gain focus when the GPS button is clicked?
This suffixIcon for the textfield is a part of it, If you click the suffixIcon, it's also performing click on the textfield. This is the reason why you are getting your keyboard poped up.
Solution:
Wrap your textfield into a Stack, and make sure IconButton is the last child of it. This performs click on your IconButton instead of gaining focus in textfield.
Stack(
alignment: Alignment.centerRight,
children: <Widget>[
TextField(),
IconButton(
icon: Icon(Icons.add),
onPressed: () {
},
),
],
)
It is a known bug, issue has ben opened on github , and closed due to inactivity... You can take a look at that issue, there are some workarounds posted by users, they mainly revolve around stacks. I'm guessing that is where Suman's answer stems from :).
I propose a different approach, simply separate the button from the TextField.
Something like this:
Row(
children: <Widget>[
Expanded(
flex: 1,
child: TextField(
decoration: InputDecoration(
border: OutlineInputBorder(),
hintText: 'Enter your address or ZIP code',
hintStyle: TextStyle(fontSize: 18),
),
)),
Expanded(
flex: 0,
child: IconButton(
icon: Icon(Icons.gps_fixed),
tooltip: 'Get a gpx fix',
onPressed: () {
print("do something");
}),
),
],
)
);
I personally prefer to have the button outside the text field because IMHO it conveys that it is a button more so than when having it inside. When inside it looks like it is just an icon that describes the field. Anyhow that is just personal preference, you can add border around both elements if that is what you prefer by wrapping both in a container and placing the decoration on the container.

TextFormField: Show suffixIcon only if text field is wide enough

I have a TextFormField component with a suffixIcon. But some of my input fields are quite some, as they only accept 2 or 3 characters. I want to hide the suffixIcon automatically if the text field is too small. Is this possible?
TextFormField(
decoration: InputDecoration(
suffixIcon: IconButton(
icon: Icon(
Icons.clear,
color: ThemeColors.iconColor,
),
onPressed: () {
_controller.clear();
},
)
),
controller: _controller
)
Edit:
The width of the text field is not fixed - I don't know its width. Usually, the text field is integrated into a flexible layout, e.g. in Rows.
So, in fact, I need to know the width of a flexible text field.
You can use the constraints provided by the LayoutBuilder and update the UI accordingly. You can use constraints.maxWidth and compare it with your value
Your code will be updated as follows
LayoutBuilder(builder: (context, constraints) {
print(constraints.maxWidth);
return TextFormField(
decoration: InputDecoration(
suffixIcon: constraints.maxWidth > YOUR_VALUE ? IconButton(
icon: Icon(
Icons.clear,
color: ThemeColors.iconColor,
),
onPressed: () {
_controller.clear();
},
) : null,
)
);
});
I hope it helps!
Yes just wrap you widget which you want to hide with Visibility and add condition to check whether the input field length is greater or smaller