Is there any way to trigger onLongPress without user interaction? - flutter

GestureDetector(
onLongPress: (){
print("LONG PRESS");
},
child:Text("......")),
Now I want to trigger onLongPress without any user interaction.
Please give your valuable reply.

Here's how you can trigger any Gesture be it onTap , onLongPress or any other.
GestureDetector gestureDetector = GestureDetector(
onLongPress: () {
print('Long Press Called');
},
child: Text('Long Press'),
);
#override
Widget build(BuildContext context) {
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
gestureDetector.onLongPress();
});
return Scaffold(
appBar: AppBar(
title: Text('Flutter Gesture'),
),
body: Center(
child: gestureDetector,
),
);
}
Output :
I/flutter (19590): Long Press Called
In this code I'm calling onLongPress on addPostFrameCallback, which will be called after widgets are loaded. You can call gestureDetector.onLongPress() whenever you want to trigger onLongPress without user interaction.

Related

Return data from a screen on Flutter, without using Navigator.pop

I have a DetailPage that must return something to the code that called it. The documentation Return data from a screen explains that you must call Navigator.pop(context, whateverYouMustReturn) on some button.
So far so good, but what happens if the user clicks on the back button on the AppBar instead?? How do I return something then??
PS I'm using Navigator 1.0, btw
Provide your own leading widget and override the callback.
AppBar(
leading: BackButton(
onPressed: () {
Navigator.of(context).pop(myData);
},
),
),
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Container(), //Make leading an empty container to hide the default back button
),
body: WillPopScope(
onWillPop: () async {
Navigator.pop(context); //This method returns future boolean, based on your condition you can either
return true; //allow you to go back or you can show a toast and restrict in this page
},
child: Container(), //Your details page widget instead of container
),
);
}

Flutter widget test - Can't tap offstage button

Here's the widget:
Widget _buildButton() {
return Offstage(
offstage: this._isOffstage,
child: TextButton(
key: Key('myBtn'),
child: Text('Click'),
onPressed: () {
print('PRESSED');
},
),
);
}
In my test:
final btnFinder = find.byKey(Key('myBtn'), skipOffstage: false);
expect(btnFinder, findsOneWidget);
await tester.tap(btnFinder);
For context, the _isOffstage flag is false, and the test passes. However, the print in the onPressed is never printed but I don't get any warnings that the button was missed. There's another button in this widget that is not wrapped in an Offstage that can be tapped, so what do I need to do differently for buttons wrapped in Offstage?

Flutter testing WillPopScope with back button

On my Home widget, when user taps system back button, It shows by a WillPopScope a confirmation dialog widget.
I want to test this dialog but I cant figure it out how to press the back button on a test file.
I had the same problem but i had no back button in my app. I wanted to test the android system back button. This is how I did it. Maybe it's helpful for people who run into the same problem as me.
testWidgets("test onWillPop",(WidgetTester tester) async {
bool willPopCalled = false;
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: WillPopScope(
onWillPop: () async {
willPopCalled = true;
return false;
},
child: Container(),
),
),
),
);
final dynamic widgetsAppState = tester.state(find.byType(WidgetsApp));
await widgetsAppState.didPopRoute();
await tester.pump();
expect(willPopCalled, true);
});
Inspired by: https://github.com/flutter/flutter/blob/master/packages/flutter/test/material/will_pop_test.dart
I cant figure it out how to press the back button on a test file.
This will help you to see back button on appbar(top part of app). It will allow you to see back button via appbar
return WillPopScope(
onWillPop: _onWillPop,
child: Scaffold(
appBar: AppBar(
title: Text("Title"),
centerTitle: true,
leading: IconButton(
icon: Icon(Icons.arrow_back, color: Colors.black),
onPressed: () => _onWillPop(),
),
),
body: Body(),
),
);
_onWillPop will be your "confirmation dialog widget" for your question.
Apparently, you cannot access Navigator in the test. So my solution is to include BackButton somewhere in the pumped widget and to pop the page like this:
await tester.pumpWidget(MaterialApp(
home: Scaffold(
body: Container(
child: BackButton(),
),
),
));
...
await tester.pageBack();

Removing keyboard focus on multiple buttons pressed

I'm trying to hide keyboard when tapped everywhere outside of textField. So I wrapped Scaffold with GestureDetector and set onTap with unfocused(). That works well however when a button is pressed then the keyboard is still active
Widget build(BuildContext context) {
return GestureDetector(
onTap: () => FocusScope.of(context).unfocus(),
child: Scaffold(
appBar: AppBar(
actions: <Widget>[FlatButton(child: Text('Done'), onPressed: () {})],
),
body: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
FlatButton(
child: Text('something'),
onPressed: () {},
),
TextField(),
],
),
),
);
}
Is there any way to remove the focus without adding that unfocused in onTap of all buttons.. Reason is I've got many buttons there and some has even onLogTap set so there would be a lot of duplicate codes
You need to also add code for hide keyboard inside onPressed() method of FlatButton
FlatButton(
child: Text('something'),
onPressed: () {
FocusScope.of(context).unfocus();
},
),
was hoping for some solution where I wouldn't need so many duplicate codes to do one thing.
AFAIK that is not possible because the click event of GestureDetector widget and click event of FlatButton both are different,
You are registering different/separate click event of FlatButton that's why your keyboard is not hiding when you click on FlatButton
Now the reason why your keyboard not hiding when pressed on buttons
Because the click event of your GestureDetector widget if overridden by the click event of your FlatButton
SOLUTION
You can do one thing, create a common method to hide the keyboard, and call that method to from button click
By thinking a little outside of the box I have managed to hide keyboard on all taps by modifying GestureDetector..
Widget build(BuildContext context) {
return GestureDetector(
onPanDown: (pd) {FocusScope.of(context).unfocus();}, //<- replaced
child: Scaffold(
appBar: AppBar(
actions: <Widget>[FlatButton(child: Text('Done'), onPressed: () {})],
),
body: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
FlatButton(
child: Text('something'),
onPressed: () {},
),
TextField(),
],
),
),
);
}
Now the keyboard will hide on taping everywhere outside of the TextField even on Buttons click.. No need to hide it in each button click. Please if you know about better solution then let me know
UPDATE:
This solution will create exception when tap on already focused TextField

Flutter disable touch on the entire screen

Is there any way to prevent my screen from receiving touch events, I don't want to disable touch for every Widget in my app. I just want to lock the app so that it doesn't receive touch events. How can I do that?
You can wrap your widget in AbsorbPointer and it won't receive touches. To enable the touch again, you can set absorbing: false
AbsorbPointer(
child: YourWidget(...),
);
Two way to do :
AbsorbPointer
IgnorePointer
Check difference with example here :
https://programmer.help/blogs/the-difference-between-flutter-absorbpointer-and-ignorepointer.html
Flutter AbsorbPointer vs IgnorePointer difference
Lets see a practical example of using IgnorePointer widget.
This case is pretty common when we started trying to implement something like toggling a selection on a widget to delete or something like this.
RESULT:
Example Senario :
Holding on a WhatsApp message and delete option coming on top. if tap anywhere else while this option active, it will go.
I implemented it like this.
appBar: AppBar(
title: Text('MyApp'),
actions: [
if (_selected != null) // <-- Delete button only appear something selected.
IconButton(
icon: Icon(Icons.delete),
onPressed: () {
// Delete Code here
}
]
),
body: GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () {
print('Tapped');
setState(() { _selected = null });
},
child: IgnorePointer(
ignoring: _selected != null ? true : false, // <-- Ignore only when selecting something.
child: Column(
children: [
...
// This is a sample message
GestureDetector(
onLongPress: () {
setState(() { _selected = messageId });
}
child: Container(
child: Text('This is a message'),
),
...
Hope it will help somebody! Have a nice day.