import 'package:flutter/material.dart'; mixin BaseFabMixin on State, TickerProvider { late bool _isFabVisible = true; AnimationController get fabAnimationCtr; Animation get fabAnimation; AnimationController _initController() { return AnimationController( vsync: this, duration: const Duration(milliseconds: 100), ); } Animation _initAnimation() { return fabAnimationCtr.drive( Tween( begin: Offset.zero, end: const Offset(0.0, 1.0), ).chain(CurveTween(curve: Curves.easeInOut)), ); } void showFab() { if (!_isFabVisible) { _isFabVisible = true; fabAnimationCtr.reverse(); } } void hideFab() { if (_isFabVisible) { _isFabVisible = false; fabAnimationCtr.forward(); } } } mixin FabMixin on BaseFabMixin { @override late final AnimationController fabAnimationCtr; @override late final Animation fabAnimation; @override void initState() { super.initState(); fabAnimationCtr = _initController(); fabAnimation = _initAnimation(); } @override void dispose() { fabAnimationCtr.dispose(); super.dispose(); } } mixin LazyFabMixin on BaseFabMixin { AnimationController? _fabAnimationCtr; Animation? _fabAnimation; @override AnimationController get fabAnimationCtr => _fabAnimationCtr ??= _initController(); @override Animation get fabAnimation => _fabAnimation ??= _initAnimation(); @override void dispose() { _fabAnimationCtr?.dispose(); super.dispose(); } } mixin _NoRightMarginMixin on StandardFabLocation { @override double getOffsetX(scaffoldGeometry, _) { return scaffoldGeometry.scaffoldSize.width - scaffoldGeometry.minInsets.right - scaffoldGeometry.floatingActionButtonSize.width; } } mixin _NoBottomPaddingMixin on StandardFabLocation { @override double getOffsetY(scaffoldGeometry, _) { return scaffoldGeometry.contentBottom - scaffoldGeometry.floatingActionButtonSize.height; } } class NoRightMarginFabLocation extends StandardFabLocation with FabFloatOffsetY, _NoRightMarginMixin { const NoRightMarginFabLocation(); } class NoBottomPaddingFabLocation extends StandardFabLocation with FabEndOffsetX, _NoBottomPaddingMixin { const NoBottomPaddingFabLocation(); } class ActionBarLocation extends StandardFabLocation with _NoBottomPaddingMixin { const ActionBarLocation(); @override double getOffsetX(scaffoldGeometry, _) { return 0.0; } }