HOW CAN I ADD onTap method for custom listview menu - flutter

I have an horizontal listview and i want to add click listener for all items which is in listview where should i use onTap method?
this is food_cart.dart
This is food category.dart
app screenshot

You can either use GestureDetector or InkWell. GestureDetector is useful to provide many other gestures like onHorizontalDragDown, onVerticalDragDown etc. While Inkwell is useful to provide ripple effect for the child widget.
InkWell(
onTap: () {
//Perform your logic here
}
child:YOUR_LISTVIEW_ITEM,
)
OR
GestureDetector(
onTap: () {
//Perform your logic here
}
child:YOUR_LISTVIEW_ITEM,
)

Wrap your FoodCard inside an Inkwell,
InkWell(
onTap: () {
//navigate to screen or show a dialog or do anything
Navigator.pushNamed(
context, '/PostDetailsScreen', arguments: mFeedData);
}
child:YOUR_FOOD_CARD,
)

Related

Gesture Detector in flutter which is not printing a text on screen after tapping

I am using gesture detector which i have specified the text widget should be printed on screen after tap.
enter image description here
Firstly its better to use GestureDetector as parent widget not in child and secondly, you are using Text in onTap function which is not proper، do not use widget inside VoidCallback functions like onTap
body: GestureDetector(
onTap: (){
print("tapped");
}
child: widget //<-- put container here
)

Flutter Tooltip on One Tap / Hold Down

My app has several textfields and I want to have a tooltip so that users know can see the definition of each field.
I came across this answer, but it wasn't helpful: Flutter Tooltip on One Tap. Therefore I decided to try and fix it myself.
Here is how to do it:
First add GestureDetector as child for Tooltip,
TooltipTriggerMode.manual for triggerMode.
add onTapDown, onTapUp, and onTapCancel as follows
Widget build(BuildContext context) {
final tooltipkey = GlobalKey<TooltipState>();
return Tooltip(
key: tooltipkey,
message: message,
triggerMode: TooltipTriggerMode.manual, // make it manual
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onTapDown: (_) => _onTapDown(tooltipkey), // add this
onTapUp: (_) => _onTapUpAndCancel(tooltipkey), // add this
onTapCancel: () => _onTapUpAndCancel(tooltipkey), // add this
child: Icon(EvaIcons.questionMarkCircleOutline),
),
);
}
and the helper functions shown inside the code above:
void _onTapDown(GlobalKey<TooltipState> tooltipkey) {
tooltipkey.currentState?.ensureTooltipVisible();
}
void _onTapUpAndCancel(GlobalKey<TooltipState> tooltipkey) {
tooltipkey.currentState?.deactivate();
}
Hooray, it works. Now you can hold down the icon to display the tooltip immediately instead of holding it down for a while (the default configuration of tooltip).

Hide circle progress inside RefreshIndicator

I am trying to use RefreshIndicator in my flutter app so i use this builtin library:
child: SafeArea(
child: RefreshIndicator(
onRefresh: () => _onRefreshData(),
child: Column(
children: <Widget>[
Expanded(...
In my page i have 2 list.when this page appear I shows a dialog and I get data from server and show these data inside of lists:
Future<void> _onRefreshData() async {
getMyChan();
}
void getMyChan() async {
Future.delayed(Duration.zero, () => _showProgressDialog());
_myChannel = await MyToolsProvider().getMe(_testToken);
getTools();
setState(() {
_closeDialog();
});
}
Now i want to use RefreshIndicator to refresh my lists but i have a question:
I just want to use swap of RefreshIndicator and don't need circle progress because as you can see i am using progressDialog in getMyChan() method so i do not need circle progress.
How can i hide circle progress inside RefreshIndicator?
Unfortunately (or not), the RefreshIndicator indicator don't have an option to hide the RefreshProgressIndicator widget present inside.
The only way is to copy the Widget in your project and replace the RefreshProgressIndicator with an empty Container here :
https://github.com/flutter/flutter/blob/f3d95cd734ad23b7f9e15e7d0bc182d40965e05f/packages/flutter/lib/src/material/refresh_indicator.dart#L459

Long Press on BottomNavigationBarItem

Is there any way to handle long press on the items of BottomNavigationBar in Flutter?
I see "onTap" event handler, but nothing else and I also cannot wrap the Items into GestureDetector.
I can wrap the whole BottomNavigationBar section into the GestureDetector but in this case it's not possible to realize which Item was pressed :-/
Thanks in advance!
After couple of days I finally understood how to realize it: you just need (as almost always) wrap Icon and Text of you bottom navigation bar items into GestureDetector widget and it works :)
The snippet would be:
new BottomNavigationBarItem(
icon: GestureDetector(
onLongPress: (){print("long tap icon");
setState(() {
_resetSct(context, i);
});
},
child: new Image.memory([skiped])), //Icon(Icons.looks_one),//photos[0].icon,
title: GestureDetector(
onLongPress: (){print("long tap title");
setState(() {
//do stuff
});
},
child: Text([skipped]))
With Flutter I recommend you to create your custom Bottom Navigation Bar as it is very easy to do.
Note: There is no way to do what you want using the default BottomNaivgationBarItem.
You need also to add enableFeedback as true and wrap your icon with GestureDetector
BottomNavigationBar(
enableFeedback: true,
This is works for me.

InkWell and GestureDetector, how to make them work?

I'd like to use a GestureDetector for it's onTapDown callback but also have a nice InkWell splash effect.
Is it possible to use these two together?
If you want to unconditionally handle the pointer down event with no gesture disambiguation, you can make the InkWell a child of a Listener, and set the onPointerDown handler.
For example:
new Listener(
onPointerDown: (e) { print('onPointerDown'); },
child: new InkWell(
child: new Text('Tap me'),
onTap: () { print('onTap'); }
),
),
It might make sense to add an onTapDown handler to InkWell.
You can pass a HitTestBehavior to GestureDetector to make it "non-blocking" by setting the value to "translucent"
Or you can also trigger it yourself using Material.of(context)
InkWell uses a GestureDetector under it's hood:
https://github.com/flutter/flutter/blob/79b5e5bc8af7d9df3374dfe6141653848d1c03ac/packages/flutter/lib/src/material/ink_well.dart#L560
The reason why a GestureDetector isn't able to work well if the InkWell-Widget is, that it sets the behavior on it's internal GestureDetector to "HitTestBehavior.opaque". This prevents "event bubbling" / event capturing on parent widgets (if my understanding is correct). And because the "behavior" is final, we can't change / fix that by our own.
https://github.com/flutter/flutter/blob/79b5e5bc8af7d9df3374dfe6141653848d1c03ac/packages/flutter/lib/src/material/ink_well.dart#L566
As I mentioned in a comment above, I wrapped the InkWell within a widget (which handles other stuff too) and provided a way to pass a callback into it which is executed on the desired event.
This is my example solution:
import 'package:flutter/material.dart';
class CardPreview extends StatefulWidget {
final dynamic data;
final VoidCallback onTap;
const CardPreview(this.data, this.onTap);
CardPreview._(this.data, this.onTap);
factory CardPreview.fromData(dynamic data, VoidCallback onTap) {
return new CardPreview(data, onTap);
}
CardPreview createState() => new CardPreview(this.data, this.onTap);
}
class CardPreviewState extends State<CardPreview> {
final dynamic data;
final VoidCallback onTap;
CardPreviewState(this.data, this.onTap);
Widget buildCard() {
return Material(
color: Colors.transparent,
child: Ink(
child: InkWell(
child: null,
onTap: () {
if (this.onTap == null) {
return;
}
this.onTap();
},
),
),
);
}
#override
Widget build(BuildContext context) {
return Container(
child: buildCard(),
);
}
}
Building on Rémi's suggestion of adding a HitTestBehavior.translucent behavior to your GestureDetector, this is how I would solve your issue:
Material(
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTapDown: (details) {
//Do something
},
child: InkWell(
onTap: () {},
child: Container(height: 20.0, width: 20.0, color: Colors.red),
),
),
),
I was able to use something similar to essentially add a onLongPressStart and onLongPressEnd to my InkWell.
InkWell has onTapDown callback now
https://api.flutter.dev/flutter/material/InkResponse/onTapDown.html
https://api.flutter.dev/flutter/material/InkWell/InkWell.html
But, GestureDetector still has more functionality than InkWell, e.g. onSecondaryTap. Thus nesting InkWell and GestureDetector is useful today.
HitTestBehavior.opaque has no impact on child-parent relationship
https://github.com/flutter/flutter/issues/18450#issuecomment-397372078
https://github.com/flutter/flutter/issues/74733#issuecomment-767859584
In short, HitTestBehavior.opaque only prevent sibling behind it from receiving events by return true in HitTest so that its direct parent won't pass on the event to its next child(in reversed order) and return true in HitTest.(Thus, sibling behind its ancestors won't receive events as well. Just like that its ancestors' behaviors are overwritten to opaque.) BUT its ancestors always DO receive events!
Remark: If A is inside B(i.e. A is a descendant of B), then B will never be behind A.
Related source:
https://api.flutter.dev/flutter/rendering/RenderBox/hitTest.html
https://api.flutter.dev/flutter/rendering/RenderProxyBoxWithHitTestBehavior/hitTest.html (RenderProxyBoxWithHitTestBehavior is used by _RenderColoredBox, which is the "color" of Container)
https://api.flutter.dev/flutter/rendering/RenderProxyBoxWithHitTestBehavior/hitTestSelf.html
https://api.flutter.dev/flutter/rendering/RenderBoxContainerDefaultsMixin/defaultHitTestChildren.html
https://api.flutter.dev/flutter/rendering/RenderStack/hitTestChildren.html (Use defaultHitTestChildren)
Acknowledgment: heavily refer to https://github.com/flutter/flutter/issues/18450#issuecomment-601865975
For onTap, only the callback of the "winner" can fire
See https://api.flutter.dev/flutter/widgets/GestureDetector-class.html
Setting GestureDetector.behavior to HitTestBehavior.opaque or HitTestBehavior.translucent has no impact on parent-child relationships: both GestureDetectors send a GestureRecognizer into the gesture arena, only one wins.
Some callbacks (e.g. onTapDown) can fire before a recognizer wins the arena, and others (e.g. onTapCancel) fire even when it loses the arena. Therefore, the parent detector in the example above may call some of its callbacks even though it loses in the arena.
This is tricky:
If winner has onTap or onTapDown, then loser's onTap will never fire, and onTapDown won't fire if the tap is too short such that gesture arena sweeping happens before onTapDown firing.
InkWell has onTap and onTapDown
https://github.com/flutter/flutter/blob/468166c713984941c0e5432b7499a1a05a0a0f61/packages/flutter/lib/src/material/ink_well.dart#L1209-L1219
Thus, to achieve best experience, all primary tap callback should be registered on InkWell. Otherwise, if GestureDetector wins, short tap won't trigger splash, else if InkWell wins, short tap won't trigger Gesture's onTapDown.