79 lines
2.3 KiB
Dart
79 lines
2.3 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
/// Retains all tab states and scroll positions, with no page-swipe recognizer.
|
|
class TabDeck extends StatefulWidget {
|
|
const TabDeck({super.key, required this.index, required this.children});
|
|
final int index;
|
|
final List<Widget> children;
|
|
@override
|
|
State<TabDeck> createState() => _TabDeckState();
|
|
}
|
|
|
|
class _TabDeckState extends State<TabDeck> with SingleTickerProviderStateMixin {
|
|
late final AnimationController _motion = AnimationController(
|
|
vsync: this,
|
|
duration: const Duration(milliseconds: 240),
|
|
value: 1,
|
|
);
|
|
int? _outgoing;
|
|
int _direction = 1;
|
|
@override
|
|
void didUpdateWidget(TabDeck oldWidget) {
|
|
super.didUpdateWidget(oldWidget);
|
|
if (oldWidget.index != widget.index) {
|
|
_outgoing = oldWidget.index;
|
|
_direction = widget.index > oldWidget.index ? 1 : -1;
|
|
if (MediaQuery.disableAnimationsOf(context)) {
|
|
_motion.value = 1;
|
|
} else {
|
|
_motion.forward(from: 0);
|
|
}
|
|
}
|
|
}
|
|
|
|
@override
|
|
void dispose() {
|
|
_motion.dispose();
|
|
super.dispose();
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) => AnimatedBuilder(
|
|
animation: _motion,
|
|
builder: (context, _) {
|
|
final t = Curves.easeOutCubic.transform(_motion.value);
|
|
return Stack(
|
|
fit: StackFit.expand,
|
|
children: [
|
|
for (var i = 0; i < widget.children.length; i++)
|
|
Offstage(
|
|
offstage:
|
|
i != widget.index && (i != _outgoing || _motion.isCompleted),
|
|
child: TickerMode(
|
|
enabled: i == widget.index,
|
|
child: IgnorePointer(
|
|
ignoring: i != widget.index,
|
|
child: ExcludeSemantics(
|
|
excluding: i != widget.index,
|
|
child: Opacity(
|
|
opacity: i == widget.index
|
|
? t
|
|
: (i == _outgoing ? 1 - t : 0),
|
|
child: Transform.translate(
|
|
offset: Offset(
|
|
(i == widget.index ? 1 - t : -t) * 22 * _direction,
|
|
0,
|
|
),
|
|
child: widget.children[i],
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
),
|
|
],
|
|
);
|
|
},
|
|
);
|
|
}
|