【发布时间】:2021-11-26 16:44:02
【问题描述】:
【问题讨论】:
标签: flutter dart flutter-layout flutter-animation flutter-alertdialog
【问题讨论】:
标签: flutter dart flutter-layout flutter-animation flutter-alertdialog
这可以通过AnimatedBuilder 和Transform 小部件来完成。使用dart:math 中的sin 函数将AnimationController 值在0.0 到1.0 之间映射成具有所需幅度的平滑正弦波。周期可以直接在AnimationController 本身中使用duration 指定。
要启动动画,您可以调用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(),
),
],
),
);
}
}
【讨论】:
WillPopScope 小部件。