Files
sm-emby-share/lib/features/player/widgets/panel_toggle_affordance.dart
T
2026-07-14 11:11:36 +08:00

104 lines
2.7 KiB
Dart

import 'package:flutter/material.dart';
class PanelToggleAffordance extends StatefulWidget {
static const double _radius = 8;
static const Color _activeFill = Color(0x2EFFFFFF);
static const Duration _openDuration = Duration(milliseconds: 220);
static const Duration _closeDuration = Duration(milliseconds: 130);
final bool isOpen;
final VoidCallback onTap;
final String? tooltip;
final EdgeInsets padding;
final Widget child;
const PanelToggleAffordance({
super.key,
required this.isOpen,
required this.onTap,
required this.child,
this.tooltip,
this.padding = const EdgeInsets.symmetric(horizontal: 8, vertical: 8),
});
@override
State<PanelToggleAffordance> createState() => _PanelToggleAffordanceState();
}
class _PanelToggleAffordanceState extends State<PanelToggleAffordance>
with SingleTickerProviderStateMixin {
late final AnimationController _ctrl;
late final Animation<double> _t;
@override
void initState() {
super.initState();
_ctrl = AnimationController(
vsync: this,
duration: PanelToggleAffordance._openDuration,
reverseDuration: PanelToggleAffordance._closeDuration,
value: widget.isOpen ? 1.0 : 0.0,
);
_t = CurvedAnimation(
parent: _ctrl,
curve: Curves.easeInOutCubic,
reverseCurve: Curves.easeInCubic,
);
}
@override
void didUpdateWidget(covariant PanelToggleAffordance oldWidget) {
super.didUpdateWidget(oldWidget);
if (oldWidget.isOpen != widget.isOpen) {
if (widget.isOpen) {
_ctrl.forward();
} else {
_ctrl.reverse();
}
}
}
@override
void dispose() {
_ctrl.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final inkWell = Material(
color: Colors.transparent,
child: InkWell(
borderRadius: BorderRadius.circular(PanelToggleAffordance._radius),
onTap: widget.onTap,
child: AnimatedBuilder(
animation: _t,
builder: (context, child) {
final fill = Color.lerp(
Colors.transparent,
PanelToggleAffordance._activeFill,
_t.value,
)!;
return Container(
padding: widget.padding,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(
PanelToggleAffordance._radius,
),
color: fill,
),
child: child,
);
},
child: widget.child,
),
),
);
final t = widget.tooltip;
if (t == null) return inkWell;
return Tooltip(message: t, child: inkWell);
}
}