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

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
)

Related

How to call the onTap method of a built GestureDetector?

I am using the flutter package AnimatedTextKit which displays some animated text.
(https://pub.dev/packages/animated_text_kit)
An AnimatedTextKit is a StatefulWidget and builds a GestureDetector :
#override Widget build(BuildContext context) {
final completeText = _currentAnimatedText.completeText(context);
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: _onTap,
child: _isCurrentlyPausing || !_controller.isAnimating
? completeText
: AnimatedBuilder(
animation: _controller,
builder: _currentAnimatedText.animatedBuilder,
child: completeText,
),
);
}
I wrap the AnimatedTextKit into a Card, and also show a yellow triangle at the bottom of the Card when the text is fully displayed :
Card containing an AnimatedTextKit
When I tap on the text : it's fine since the AnimatedTextKit GestureDetector detects the tap. But when I tap on the yellow triangle just below, because I tap outside the AnimatedTextKit widget, the tap is not detected, which is normal.
Is there a clean way to make a tap made anywhere on the Card be interpreted as a tap on the AnimatedTextKit ?
I have looked at these answers : How to pass Taps to widgets below the top widget? and How do I programmatically simulate onTap on a button in Flutter? but I feel like I'm not able to apply the proposed solutions since I cannot modify the AnimatedTextKit library code.

Flutter. How to disable "Double tap to activate, double tap and hold to long press" hint in accessibility mode

Currently, I'm working with Accessibility in Flutter and on android devices it's pronouncing this hint: "double tap to activate, double tap and hold to long press".
As far as I know this hint pronounced if widget is clickable, so I tried wrapping child of this widget with BlockSemantics (didn't work), also wrapped this clickable widget with Semantics and set property button: false but that also didn't help.
This how my widget looks.
return GestureDetector(
behavior: HitTestBehavior.opaque,
onTap: () => widget.onItemSelect(),
onLongPress: () => widget.onItemLongPress(),
child: childWidget,
);
How can I disable this?
GestureDetector has a excludeSemantics property, so I set it to true. It will NOT block child widget's semantics, it will just disable semantics for GestureDetector widget itself, and as a result Android accessibility hint also turn off

Flutter: how to make card expand to whole screen?

I have some cards in gridview. I want ontap of any card, they should expand to whole screen.
this are the cards,
HAVE TO DELETE IMAGES BECAUSE OF CONFIDENTIALITY
I want them to expand to whole screen like this,
what I have tried,
-> I have tried using OpenContainer widget,
-> custom hero animation
but they both use pageroute but I want them to do it without the page route because there is some content like appbar which would be same for both screen so I don't want them rebuild it everytime user tap on any of the card.
if anyone can lead me to right direction that would be awesome
Take a look at this package: https://pub.dev/packages/animations
if you don't like using pageroute you can just switch your widget using StatefulWidget and Visibility.
And wrap your Card with InkWell then use the onTap / onPressed callback to set change the state so the Visibility will start work now
Create a function
Widget transition(Widget _child) {
return PageTransitionSwitcher(
duration: const Duration(milliseconds: 800),
transitionBuilder: (
Widget child,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
return SharedAxisTransition(
child: child,
animation: animation,
secondaryAnimation: secondaryAnimation,
transitionType: SharedAxisTransitionType.horizontal,
);
},
child: _child,
);
}
Add it on your scaffold:
transition(child:condition ? widget_1 : widget_2);
I'm not 100% sure what you meant by expand to the whole screen, but you probably need to use the Hero() widget, wrap each widget you want to expand with a Hero() widget and give it a tag: 'spo2' for example, make a new screen for the second image, wrap each card with a Hero() and the same tag in the previous screen for the expanded card.
For further reading check out https://api.flutter.dev/flutter/widgets/Hero-class.html
Try using a dialogue and animating the opening.

HOW CAN I ADD onTap method for custom listview menu

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,
)

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.