| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123 |
- import 'package:flutter/cupertino.dart';
- import 'package:flutter/material.dart';
- class AnimatedSwitcherWidget extends StatefulWidget {
- final SwitcherController controller;
- final Duration duration;
- const AnimatedSwitcherWidget({
- super.key,
- required this.controller,
- this.duration = const Duration(milliseconds: 1500),
- });
- @override
- State<AnimatedSwitcherWidget> createState() => _AnimatedSwitcherWidgetState();
- }
- class _AnimatedSwitcherWidgetState extends State<AnimatedSwitcherWidget> {
- Widget? _currentWidget;
- @override
- void initState() {
- super.initState();
- // 注册更新回调
- widget.controller._registerOnUpdate(() => setState(() {
- _currentWidget = widget.controller._currentWidget;
- }));
- }
- @override
- Widget build(BuildContext context) {
- return ClipRRect(
- child: AnimatedSwitcher(
- duration: widget.duration,
- transitionBuilder: (Widget child, Animation<double> animation) {
- return SlideTransitionX(
- direction: AxisDirection.down,
- position: animation,
- child: child,
- );
- },
- child: Center(key: ValueKey(_currentWidget), child: _currentWidget),
- ),
- );
- }
- }
- class SwitcherController {
- // 保存当前组件和回调函数
- Widget? _currentWidget;
- VoidCallback? _onUpdate;
- // 更新组件并触发回调
- void updateWidget(Widget newWidget) {
- _currentWidget = newWidget;
- _onUpdate?.call();
- }
- // 注册更新回调(供State内部调用)
- void _registerOnUpdate(VoidCallback onUpdate) {
- _onUpdate = onUpdate;
- }
- }
- class SlideTransitionX extends AnimatedWidget {
- SlideTransitionX({
- super.key,
- required Animation<double> position,
- this.transformHitTests = true,
- this.direction = AxisDirection.down,
- required this.child,
- }) : super(listenable: position) {
- switch (direction) {
- case AxisDirection.up:
- _tween = Tween(begin: const Offset(0, 1), end: const Offset(0, 0));
- break;
- case AxisDirection.right:
- _tween = Tween(begin: const Offset(-1, 0), end: const Offset(0, 0));
- break;
- case AxisDirection.down:
- _tween = Tween(begin: const Offset(0, -1), end: const Offset(0, 0));
- break;
- case AxisDirection.left:
- _tween = Tween(begin: const Offset(1, 0), end: const Offset(0, 0));
- break;
- }
- }
- final bool transformHitTests;
- final Widget child;
- final AxisDirection direction;
- late final Tween<Offset> _tween;
- @override
- Widget build(BuildContext context) {
- final position = listenable as Animation<double>;
- Offset offset = _tween.evaluate(position);
- if (position.status == AnimationStatus.reverse) {
- switch (direction) {
- case AxisDirection.up:
- offset = Offset(offset.dx, -offset.dy);
- break;
- case AxisDirection.right:
- offset = Offset(-offset.dx, offset.dy);
- break;
- case AxisDirection.down:
- offset = Offset(offset.dx, -offset.dy);
- break;
- case AxisDirection.left:
- offset = Offset(-offset.dx, offset.dy);
- break;
- }
- }
- return FractionalTranslation(
- translation: offset,
- transformHitTests: transformHitTests,
- child: child,
- );
- }
- }
|