I would like to create custom onTap
(or any on other onTap
callbacks provided by GestureDetector
"indicator" where content(child) is scaled-down and text becomes darker, like to this:
Is there already a prebuilt package for that type of animation? If not can you at least fix snippet below.
I tried creating one using AnimationController
, Transform.scale
and various combinations of onTap
callbacks but it's pretty unresponsive (gets 'stuck' all the time)
Here is a basic snippet:
double squareScaleA = 1;
AnimationController _controllerA;
@override
void initState() {
_controllerA = AnimationController(
vsync: this,
lowerBound: 0.9,
upperBound: 1.0,
duration: Duration(milliseconds: 100));
_controllerA.addListener(() {
setState(() {
squareScaleA = _controllerA.value;
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
onTapDown: (dp) {
_controllerA.forward();
},
onTapUp: (dp) {
_controllerA.reverse();
},
child: Transform.scale(
scale: squareScaleA,
child: widget.child,
),
);
}
I found the issue with my code, the animation was "reversed", on onTapDown would cause child
to expand (nothing happened since child
was already at max scale), so I just reversed _controllerA.reverse
and _controllerA.forward
(actually replaced _controllerA.forward
with _controllerA.fling
).
This is final code:
class OnTapScaleAndFade extends StatefulWidget {
final Widget child;
final void Function() onTap;
const OnTapScaleAndFade({Key key, this.child, this.onTap}) : super(key: key);
@override
_OnTapScaleAndFadeState createState() => _OnTapScaleAndFadeState();
}
class _OnTapScaleAndFadeState extends State<OnTapScaleAndFade>
with TickerProviderStateMixin {
double squareScaleA = 1;
AnimationController _controllerA;
@override
void initState() {
_controllerA = AnimationController(
vsync: this,
lowerBound: 0.98,
upperBound: 1.0,
value: 1,
duration: Duration(milliseconds: 10),
);
_controllerA.addListener(() {
setState(() {
squareScaleA = _controllerA.value;
});
});
super.initState();
}
@override
Widget build(BuildContext context) {
return GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
_controllerA.reverse();
widget.onTap();
},
onTapDown: (dp) {
_controllerA.reverse();
},
onTapUp: (dp) {
Timer(Duration(milliseconds: 150), () {
_controllerA.fling();
});
},
onTapCancel: () {
_controllerA.fling();
},
child: Transform.scale(
scale: squareScaleA,
child: widget.child,
),
);
}
@override
void dispose() {
_controllerA.dispose();
super.dispose();
}
}
Feel free to add your custom gesture callbacks, I needed only onTap.