我想像这样摇动警报对话框:(不仅是文本,还有整个弹出对话框)
https://www.youtube.com/watch?v=IaHMoifUBSw
当用户单击按钮时,如何摇动整个警报对话框?
这可以通过AnimatedBuilder
和Transform
小部件来完成。使用sin
函数 from将 to之间的值dart:math
映射为具有所需幅度的平滑正弦波。周期可以直接使用本身指定。AnimationController
0.0
1.0
duration
AnimationController
要启动动画,您可以调用controller.repeat()
以使其无限期运行,直到您调用controller.stop()
,或者您可以使用controller.forward()
运行一次。
例如,让它摇动 3 次然后停止,您可以这样做:
onPressed: () async {
await _controller.forward(from: 0.0);
await _controller.forward(from: 0.0);
await _controller.forward(from: 0.0);
},
这是它的实际效果(请注意 GIF 的帧速率限制):
下面附有完整的源代码供您用作起点。您可以调整duration
和distance
更改晃动动画的强度:
import 'dart:math';
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Test(),
);
}
}
class Test extends StatelessWidget {
const Test({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Shaking Dialog Demo')),
body: Center(
child: ElevatedButton(
child: Text('Show Dialog'),
onPressed: () {
showDialog(
context: context,
builder: (_) => ShakeableDialog(),
);
},
),
),
);
}
}
class ShakeableDialog extends StatefulWidget {
final Duration duration; // how fast to shake
final double distance; // how far to shake
const ShakeableDialog({
Key? key,
this.duration = const Duration(milliseconds: 300),
this.distance = 24.0,
}) : super(key: key);
@override
_ShakeableDialogState createState() => _ShakeableDialogState();
}
class _ShakeableDialogState extends State<ShakeableDialog>
with SingleTickerProviderStateMixin {
late final _controller = AnimationController(
vsync: this,
duration: widget.duration,
);
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
builder: (BuildContext context, Widget? child) {
final dx = sin(_controller.value * 2 * pi) * widget.distance;
return Transform.translate(
offset: Offset(dx, 0),
child: child,
);
},
child: AlertDialog(
title: Text('Alert Dialog Title'),
content: Text('Try these buttons!'),
actions: [
TextButton(
child: Text('SHAKE 3 TIMES'),
onPressed: () async {
await _controller.forward(from: 0.0);
await _controller.forward(from: 0.0);
await _controller.forward(from: 0.0);
},
),
TextButton(
child: Text('KEEP SHAKING'),
onPressed: () => _controller.repeat(),
),
TextButton(
child: Text('STOP SHAKING'),
onPressed: () => _controller.stop(),
),
TextButton(
child: Text('CLOSE'),
onPressed: () => Navigator.of(context).pop(),
),
],
),
);
}
}