Reputation: 2537
I am currently using a GestureDetector()
to create a custom button with an AnimatedContainer()
.
Goal is to get some sort of animation beeing scale, color, shadow or whatever once the user presses and releases the button.
My problem right now is that the onTapDown()
callback is delayed. Maybe its because this button is actually an item within a SliverList
which causes the delay. However if I tap on the GestureDetector without scrolling it takes a couple of hundred milliseconds until the onTapDown
callback fires. Why?
I do understand that flutter and basically any other UI framework needs some sort of delayed touch for objects within a list. It has to determine of the user wants to scroll or press the button.
But do you have any ideas how I can display a nice scale animation once a user presses this container?
Here's the SliverList
containing the RecipeMetaItem
(which then reacts to touch input).
SliverList(
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
MetaItem metaItem = state.metaItems[index];
return RecipeMetaItem(metaItem: metaItem, height: 178);
},
childCount: state.metaItems.length,
),
)
And here is the portion of the RecipeMetaItem()
class RecipeMetaItem extends StatefulWidget {
final double height;
final MetaItem metaItem;
const RecipeMetaItem({Key key, this.metaItem, this.height = 200}) : super(key: key);
@override
RecipeMetaItemState createState() {
return new RecipeMetaItemState();
}
}
class RecipeMetaItemState extends State<RecipeMetaItem> {
double offset;
@override
void initState() {
super.initState();
offset = 0.0;
}
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.only(left: 10.0, right: 10.0, bottom: 20.0),
child: GestureDetector(
onTapDown: (details) {
setState(() {
offset = -10;
});
},
onTapUp: (details) {
setState(() {
offset = 0;
});
},
child: AnimatedContainer(
duration: Duration(milliseconds: 60),
curve: Curves.easeOut,
transform: Matrix4.translationValues(0, offset, 0),
child: Column(
children: <Widget>[
Container(
height: widget.height,
decoration: new BoxDecoration(
boxShadow: [
BoxShadow(
color: Colors.black.withAlpha(40),
blurRadius: 12.5,
spreadRadius: 0.0,
)
],
borderRadius: BorderRadius.all(Radius.circular(10)),
),
child: ClipRRect(
borderRadius: BorderRadius.all(Radius.circular(10)),
child: Stack(
children: [
CachedNetworkImage(
fit: BoxFit.cover,
imageUrl: widget.metaItem.imageUrl,
fadeInDuration: Duration(milliseconds: 50),
errorWidget: (context, url, error) => new Icon(Icons.error),
),
],
),
),
),
Padding(
padding: const EdgeInsets.only(top: 8.0, left: 4.0, right: 4.0),
child: Row(
children: <Widget>[
Expanded(
child: Text(
widget.metaItem.title,
textAlign: TextAlign.left,
style: TextStyle(fontWeight: FontWeight.w700, fontSize: 17.0),
),
),
],
),
)
],
),
),
),
);
}
}
Thanks!
Upvotes: 4
Views: 2479
Reputation: 806
Not sure if you solved this one, but I found a similar question here on S.O. and I think the same solution might work for you!
Try switching the GestureDetector to a Listener and replacing the:
onTapDown: (details) {
setState(() {
offset = -10;
});
},
onTapUp: (details) {
setState(() {
offset = 0;
});
},
with:
onPointerDown: (PointerDownEvent event) {
setState(() {
offset = -10;
});
},
onPointerUp: (PointerUpEvent event) {
setState(() {
offset = 0;
});
},
Hopefully that solves it, in which case the issue would be the GestureDetector, not the child widget.
Upvotes: 5