Flutter Global Keyboard Shortcuts - flutter

I am writing an application that should support searching some content. For this I implemented a search TextField. Now I would like to focus said TextField when the key combination ctrl + F is pressed.
In order to implement this, I wrapped my view in both a Shortcuts and Actions component as follows:
return Scaffold(
body: Shortcuts(
shortcuts: {
LogicalKeySet(LogicalKeyboardKey.keyF, LogicalKeyboardKey.control): MTCSearchIntent(),
},
child: Actions(
actions: {
MTCSearchIntent: MTCFocusAction(null),
},
child: ...
),
),
);
This implementation works if the search bar is already focused, but that kind of defeats the purpose of focusing it.. So I was wondering, how can I apply the Shortcut listener to the entire screen? Or asked differently, what determines the scope of the interactions, the Shortcut component, the Action component, something related to the FocusNode?
The example on flutter.dev don't seem to work globally either. In fact they don't seem to work at all for me.
I reproduced the example using a minimal example here: https://dartpad.dev/?id=55902a179be137d9025ea02170d749a7
When the TextField is focused, the ArrowUpand ArrowDown actions work as intended. However, if any other part of the application is highlighted, the Intent is never triggered.

Related

How to ignore enter button on keyboard for flutter web?

For flutter web, pressing enter triggers an event. How can I ignore the use case where the user presses the enter key on their keyboard
Did you try this way?
import 'package:flutter/services.dart';
MaterialApp(
shortcuts: Map.of(WidgetsApp.defaultShortcuts)
..remove(LogicalKeySet(LogicalKeyboardKey.enter)), //<-- add this to materialapp
...
)
to ignore keyboard on widget i had many search and i found a solution, but im not sure about it:
you can use ShortcutManager
Shortcuts.manager(
manager: ShortcutManager(
shortcuts: Map.of(WidgetsApp.defaultShortcuts)
..remove(LogicalKeySet(LogicalKeyboardKey.enter))
..remove(LogicalKeySet(LogicalKeyboardKey.numpadEnter)),
),
child: TextField(),
),
i hope this works

Call a function when user press a Key from Keyboard in Flutter

how can I call a function when the user presses a key from the keyboard ?
This is for Desktop development .
You can do it using Actions and shortcuts in flutter. These widgets work something like this :
To get a more detailed information, please refer to the flutter docs here. These come under Advanced UI concepts.
I imagine you're using a TextField? It has the following property onChanged: ((newText) => {})
You can go ahead and use it like this:
onChanged: ((newText) => { yourFunction; }),
or
onChanged: ((newText) => { setState((){yourFunction;}); }),
Just to clarify, this will only update when the text changes. #Divyam Dhadwal seems to have a wild answer that might be more useful
Good luck my man! xx

Instantsearch.js Submit hide on search?

Problem:
By default in instantsearch.js, the reset button in the search field is hidden until you start typing. However the submit button doesn't hide, causing them to overlap, this seems default behavior(?)
Here is a demo that demonstrates the issue:
https://codesandbox.io/s/quizzical-leakey-7shzr
Expected Outcome:
I want the search submit button to replace (toggle) with the reset button on typing.
Things I've tried:
I have looked through the documentation and can't find any solution to this. There is a showReset and showSubmit parameters as seen here: https://www.algolia.com/doc/api-reference/widgets/search-box/js/ but these just disable them completely.
Changing the template for them in the widget, only stylizes them, rather than adjust their function.
I do have a heavy handed solution I've written in jquery below but my question is: Is there a way to configure this behavior in instantsearch.js?
$( ".ais-SearchBox-input" ).on("keyup", function() {
if($('.ais-SearchBox-input').val().length > 0){
$('.ais-SearchBox-submit').addClass('none');
}else{
$('.ais-SearchBox-submit').removeClass('none');
}
});
$(document).on('click', '.ais-SearchBox-reset', function() {
$('.ais-SearchBox-submit').removeClass('none');
});
The submit button is initially designed to be on the left hand side of the searchbox, and the reset one on the right hand side, as you can see in the InstantSearch.js SearchBox Storybook. In your demo, there's custom CSS that aligns them both on the right, which is why they're overlapping. But they're two orthogonal concepts, so they weren't designed to replace one another out of the box.
Your solution is fine, although I understand that having imperative logic like this on top of InstantSearch.js might feel icky. Another approach is to directly hook into the rendering logic of the widget by using the connectSearchBox connector. You'll be able to fully control what is rendered, and you'll have access to query which you'll be able to leverage to decide whether to show one button or the other.
My advice is to start from the full example and adapt it for your use case.

Flutter Floating Action Button with Dynamic Status

Putting the finishing touches on my first Flutter mobile app.
Another important ToDo: My Floating Action Button appears in the Top App Bar for every page, but i would like its status to change (enabled / disabled) depending on the current page. Is this possible? if so, any tutorials, resources, reference material and / or code examples fit for a novice, would be much appreciated.
Thanks!
Cool, you can use Visibility:
floatingActionButton: Visibility(
child: FloatingActionButton(...),
visible: false, // set it to false
)
Alternatively, you could use NotificationListener (more elegante but sophisticated).
Please check this example from another publication
Edit: maybe controlling it directly in onPressed.
According to official docs:
"If the onPressed callback is null, then the button will be disabled and by default will resemble a flat button in the disabledColor."
FloatingActionButton(
onPressed: shouldButtonBeDisabled() ? null : () => whatToDoOnPressed,
child: Text('blablabla')
);

InheritedWidget update cause problems

I use the inherited widget at the top of my app to update my application whenever a new location is setted. This results in a refresh of my location coordinates at every possible place in my app.
However I also have a textfield. When i tap on the textfield some seconds later
the keyboard will be hidden by the update of the inherited widget.
Is there a way to prevent flutter to hide the keyboard or to reinitialize the state so that the update of the inherited widgets works together with my search field?
It should be also possible that when i enter some text that this trigger the inherited widget for a new update but the search bar and keyboard should stay open.
new TextField(
controller: _controller,
autocorrect: false,
autofocus: true
...
)
Without seeing all of your code, it's a little bit difficult to know what's going on.
My best guess though is that you're using a context somewhere above the TextField to register for updates from the inherited widget.
What I'd advise you to do though is go up the widget tree from your TextField and make sure that you're not using the inherited widget in a context anywhere above it. It might be worth putting some debug statements at the beginning of your build methods to determine exactly where the build is being triggered from (the inherited widget shouldn't trigger a rebuild immediately below it if you're using it right, but stranger things have happened).
This includes if you have something like this:
MyWidget extends StatelessWidget {
Widget build(BuildContext context) {
Location location = MyInheritedWidget.of(context).location;
return new Row(
children: [
new LocationDisplayer(location),
new TextField( ..... ),
],
);
}
}
The reason I say this is that from my understanding of how inherited widgets work; when it changes, whichever widgets whose contexts were used to get the inherited widget get rebuilt.
That means that even though your textfield technically isn't changing any properties, it might actually be a new textfield depending on how the build went (there's a bit of flutter magic I don't fully understand around how they decide when to make new vs re-build things) and therefore it hasn't requested focus.
Rather than having to write a bunch of new widgets to enclose whatever is using MyInheritedWidget, I believe you could use something like this:
MyWidget extends StatelessWidget {
Widget build(BuildContext context) {
return new Row(
children: [
new Builder(
builder: (context) {
Location location = MyInheritedWidget.of(context).location;
return new LocationDisplayer(location);
},
),
new TextField( ..... ),
],
);
}
}
If you're 100% sure you're not doing this anywhere, then you could go for the non-flutter way of doing things... your location class could expose a subscribe and unsubscribe method. All of the widgets where you're actually using the location call subscribe (which should also be stateful widgets) with a callback in their initState() and unsubscribe in their dispose(). The location class would simply call each of the callbacks instead of changing state as you're doing now, and within each of the callbacks you should call setState for the widget that actually shows the location.