如何在按下按钮时创建动画。例如,像反射应用中的弹跳动画。
我到目前为止所做的:
AnimationController _animationController;
Animation<double> _animation;
@override
void initState() {
_animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 2000),
);
_animation =
CurvedAnimation(parent: _animationController, curve: Curves.bounceInOut);
super.initState();
}
答案 0 :(得分:1)
应该执行以下操作:
class AnimatedButton extends StatefulWidget {
@override
_AnimatedButtonState createState() => _AnimatedButtonState();
}
class _AnimatedButtonState extends State<AnimatedButton>
with SingleTickerProviderStateMixin {
AnimationController _animationController;
@override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(milliseconds: 200),
lowerBound: 0.0,
upperBound: 0.1,
);
_animationController.addListener(() {
setState(() {});
});
}
@override
Widget build(BuildContext context) {
double scale = 1 - _animationController.value;
return GestureDetector(
onTapUp: _onTapUp,
onTapDown: _onTapDown,
child: Transform.scale(
scale: scale,
child: Container(
width: 300,
height: 75,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.circular(38.0),
boxShadow: [
BoxShadow(
color: Colors.black26,
offset: Offset(0.0, 2.0),
blurRadius: 5.0,
spreadRadius: 0.25,
),
],
),
),
),
);
}
void _onTapDown(TapDownDetails details) {
_animationController.forward();
}
void _onTapUp(TapUpDetails details) {
_animationController.reverse();
}
}
答案 1 :(得分:1)
实际调用
_controller.addListener(() {
setState(() {});
});
可能会导致一些严重的性能问题并导致动画滞后。更多信息在这里: https://medium.com/flutter-community/flutter-laggy-animations-how-not-to-setstate-f2dd9873b8fc
所以我建议改为这样做:
class BouncingWidget extends StatefulWidget {
final Widget child;
final VoidCallback onPress;
BouncingWidget({@required this.child, Key key, this.onPress})
: assert(child != null),
super(key: key);
@override
_BouncingWidgetState createState() => _BouncingWidgetState();
}
class _BouncingWidgetState extends State<BouncingWidget>
with SingleTickerProviderStateMixin {
Animation<double> _scale;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: const Duration(milliseconds: 50),
);
_scale = Tween<double>(begin: 1.0, end: 0.9)
.animate(CurvedAnimation(parent: _controller, curve: Curves.ease));
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Listener(
onPointerDown: (PointerDownEvent event) {
_controller.forward();
},
onPointerUp: (PointerUpEvent event) {
_controller.reverse();
if (widget.onPress == null) return;
widget.onPress();
},
child: ScaleTransition(
scale: _scale,
child: widget.child,
),
);
}
}
答案 2 :(得分:0)
也尝试这个。这可能有帮助:)
import 'package:flutter/material.dart';
class MyApp extends StatefulWidget {
@override
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with SingleTickerProviderStateMixin {
double _scale;
AnimationController _controller;
@override
void initState() {
_controller = AnimationController(
vsync: this,
duration: Duration(
milliseconds: 200,
),
lowerBound: 0.0,
upperBound: 0.1,
)..addListener(() {
setState(() {});
});
super.initState();
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
_scale = 1 - _controller.value;
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text('Tap on the Below Button',style: TextStyle(color: Colors.grey[400],fontSize: 20.0),),
SizedBox(
height: 20.0,
),
Center(
child: GestureDetector(
onTapDown: _onTapDown,
onTapUp: _onTapUp,
onLongPressMoveUpdate: _onMove,
child: Transform.scale(
scale: _scale,
child: _animatedButtonUI,
),
),
),
],
),
),
);
}
Widget get _animatedButtonUI => Container(
height: 70,
width: 200,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(100.0),
boxShadow: [
BoxShadow(
color: Color(0x80000000),
blurRadius: 30.0,
offset: Offset(0.0, 5.0),
),
],
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
Color(0xFF0000FF),
Color(0xFFFF3500),
],
)),
child: Center(
child: Text(
'tap',
style: TextStyle(
fontSize: 30.0,
fontWeight: FontWeight.bold,
color: Colors.white),
),
),
);
void _onTapDown(TapDownDetails details) {
_controller.forward();
}
void _onTapUp(TapUpDetails details) {
_controller.reverse();
}
void _onMove(LongPressMoveUpdateDetails details){
_controller.reverse();
}
}
答案 3 :(得分:0)
这里的其他解决方案使用带有onTapUp和onTapDown的GestureDetector。但是,onTapDown在用户点击屏幕时会有一些延迟,并且要求他们按住按钮才能真正被点击。要解决此问题,请将Listener小部件与onPointerDown和onPointerUp结合使用。
curl_easy_setopt(curl, CURLOPT_PASSWORD, apikey.c_str());
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
答案 4 :(得分:0)
如果要使其禁用动画,然后将其设为onPress null并传递子代,也可以将此窗口小部件类也用于此目的。
import 'package:flutter/material.dart';
class Bouncing extends StatefulWidget {
final Widget child;
final VoidCallback onPress;
Bouncing({@required this.child, Key key, this.onPress})
: assert(child != null),
super(key: key);
@override
_BouncingState createState() => _BouncingState();
}
class _BouncingState extends State<Bouncing>
with SingleTickerProviderStateMixin {
double _scale;
AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this,
duration: Duration(milliseconds: 100),
lowerBound: 0.0,
upperBound: 0.1,
);
_controller.addListener(() {
setState(() {});
});
}
@override
void dispose() {
super.dispose();
_controller.dispose();
}
@override
Widget build(BuildContext context) {
_scale = 1 - _controller.value;
return Listener(
onPointerDown: (PointerDownEvent event) {
if (widget.onPress != null) {
_controller.forward();
}
},
onPointerUp: (PointerUpEvent event) {
if (widget.onPress != null) {
_controller.reverse();
widget.onPress();
}
},
child: Transform.scale(
scale: _scale,
child: widget.child,
),
);
}
}
用法:
Bouncing(
onPress: (){},
child: Container()
);
输出: