76 lines
2.1 KiB
Dart
76 lines
2.1 KiB
Dart
import 'dart:math';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:provider/provider.dart';
|
|
import '../../providers/settings_provider.dart';
|
|
|
|
class ShakeWidget extends StatefulWidget {
|
|
final Widget child;
|
|
final double shakeOffset;
|
|
final int shakeCount;
|
|
final Duration duration;
|
|
|
|
const ShakeWidget({
|
|
super.key,
|
|
required this.child,
|
|
this.shakeOffset = 30.0,
|
|
this.shakeCount = 3,
|
|
this.duration = const Duration(milliseconds: 400),
|
|
});
|
|
|
|
@override
|
|
ShakeWidgetState createState() => ShakeWidgetState();
|
|
}
|
|
|
|
class ShakeWidgetState extends State<ShakeWidget>
|
|
with SingleTickerProviderStateMixin {
|
|
late AnimationController _controller;
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
_controller = AnimationController(vsync: this, duration: widget.duration);
|
|
_controller.addStatusListener((status) {
|
|
if (status == AnimationStatus.completed) {
|
|
_controller.reset();
|
|
}
|
|
});
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_controller.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
void shake() {
|
|
_controller.forward();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
// Read settings from provider (listen: false because we only read in build,
|
|
// actually we want to listen to updates if settings change while looking at it?
|
|
// But usually ShakeWidget is in BattleScreen.
|
|
// However, the previous implementation used `widget.shakeCount` and `widget.shakeOffset`.
|
|
// We should prefer provider values if available, or allow overrides?
|
|
// The prompt says "shakeWidget에서 shakeCount, shakeOffset을 settings에서 설정할 수 있게 globalOption으로 설정해야해."
|
|
// So we use Provider values.
|
|
|
|
final settings = context.watch<SettingsProvider>();
|
|
final shakeCount = settings.shakeCount;
|
|
final shakeOffset = settings.shakeOffset;
|
|
|
|
return AnimatedBuilder(
|
|
animation: _controller,
|
|
builder: (context, child) {
|
|
final double sineValue = sin(shakeCount * 2 * pi * _controller.value);
|
|
return Transform.translate(
|
|
offset: Offset(sineValue * shakeOffset, 0),
|
|
child: child,
|
|
);
|
|
},
|
|
child: widget.child,
|
|
);
|
|
}
|
|
}
|