didvan-app/lib/views/widgets/didvan/bnb.dart

333 lines
11 KiB
Dart

import 'package:didvan/config/design_config.dart';
import 'package:didvan/config/theme_data.dart';
import 'package:didvan/views/widgets/didvan/text.dart';
import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';
class DidvanBNB extends StatelessWidget {
final int currentTabIndex;
final void Function(int index) onTabChanged;
const DidvanBNB(
{Key? key, required this.currentTabIndex, required this.onTabChanged})
: super(key: key);
@override
Widget build(BuildContext context) {
return Container(
height: 72,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.surface,
borderRadius: const BorderRadius.vertical(top: Radius.circular(0)),
border: const Border(
top: BorderSide(
color: Color.fromARGB(255, 224, 224, 224),
width: 1.5,
),
),
),
padding: const EdgeInsets.symmetric(horizontal: 12),
child: Row(
children: [
_NavBarItem(
isSelected: currentTabIndex == 1,
title: 'رسانه',
selectedIconPath:
'lib/assets/icons/media selected.svg', // Selected SVG icon
unselectedIconPath:
'lib/assets/icons/media.svg', // Unselected SVG icon
onTap: () => onTabChanged(1),
),
_NavBarItem(
isSelected: currentTabIndex == 4,
title: 'هوشان',
selectedIconPath:
'lib/assets/icons/houshan_selected.svg', // Selected SVG icon
unselectedIconPath:
'lib/assets/icons/bot.svg', // Unselected SVG icon
onTap: () => onTabChanged(4),
),
_NavBarItem(
isSelected: currentTabIndex == 0,
title: 'خانه',
selectedIconPath: DesignConfig.isDark
? 'lib/assets/icons/selected home.svg'
: 'lib/assets/icons/selected home.svg',
unselectedIconPath: DesignConfig.isDark
? 'lib/assets/icons/home2.svg'
: 'lib/assets/icons/home2.svg', // Unselected SVG icon
onTap: () => onTabChanged(0),
),
_NavBarItem(
isSelected: currentTabIndex == 2,
title: 'نبض صنعت',
selectedIconPath: DesignConfig.isDark
? 'lib/assets/icons/Nabz_Sanat.svg'
: 'lib/assets/icons/Nabz_Sanat.svg', // Selected SVG icon
unselectedIconPath: DesignConfig.isDark
? 'lib/assets/icons/chart 2.svg'
: 'lib/assets/icons/chart 2.svg', // Unselected SVG icon
onTap: () => onTabChanged(2),
),
_NavBarItem(
isSelected: currentTabIndex == 3,
title: 'کاوش',
selectedIconPath:
'lib/assets/icons/explore select.svg', // Selected SVG icon
unselectedIconPath:
'lib/assets/icons/discover.svg', // Unselected SVG icon
onTap: () => onTabChanged(3),
),
],
),
);
}
}
class _NavBarItem extends StatefulWidget {
final VoidCallback onTap;
final bool isSelected;
final String title;
final String selectedIconPath;
final String unselectedIconPath;
final bool isHomeButton;
const _NavBarItem({
Key? key,
required this.isSelected,
required this.title,
required this.selectedIconPath,
required this.unselectedIconPath,
required this.onTap,
// ignore: unused_element_parameter
this.isHomeButton = false,
}) : super(key: key);
@override
State<_NavBarItem> createState() => _NavBarItemState();
}
class _NavBarItemState extends State<_NavBarItem>
with TickerProviderStateMixin {
late AnimationController _scaleController;
late AnimationController _bounceController;
late AnimationController _rippleController;
late Animation<double> _scaleAnimation;
late Animation<double> _bounceAnimation;
late Animation<double> _rippleAnimation;
bool _isPressed = false;
@override
void initState() {
super.initState();
_scaleController = AnimationController(
duration: const Duration(milliseconds: 150),
vsync: this,
);
_bounceController = AnimationController(
duration: const Duration(milliseconds: 600),
vsync: this,
);
_rippleController = AnimationController(
duration: const Duration(milliseconds: 400),
vsync: this,
);
_scaleAnimation = Tween<double>(
begin: 1.0,
end: 0.85,
).animate(CurvedAnimation(
parent: _scaleController,
curve: Curves.easeInOut,
));
_bounceAnimation = Tween<double>(
begin: 1.0,
end: 1.2,
).animate(CurvedAnimation(
parent: _bounceController,
curve: Curves.elasticOut,
));
_rippleAnimation = Tween<double>(
begin: 0.0,
end: 1.0,
).animate(CurvedAnimation(
parent: _rippleController,
curve: Curves.easeOut,
));
}
@override
void dispose() {
_scaleController.dispose();
_bounceController.dispose();
_rippleController.dispose();
super.dispose();
}
void _onTapDown() {
setState(() {
_isPressed = true;
});
_scaleController.forward();
_rippleController.forward();
}
void _onTapUp() {
setState(() {
_isPressed = false;
});
_scaleController.reverse();
_rippleController.reverse();
if (widget.isSelected) {
_bounceController.forward().then((_) {
_bounceController.reverse();
});
}
widget.onTap();
}
void _onTapCancel() {
setState(() {
_isPressed = false;
});
_scaleController.reverse();
_rippleController.reverse();
}
@override
Widget build(BuildContext context) {
return Expanded(
child: Tooltip(
message: widget.title,
decoration: BoxDecoration(
color: Theme.of(context).colorScheme.title,
borderRadius: DesignConfig.highBorderRadius,
boxShadow: DesignConfig.defaultShadow,
),
child: GestureDetector(
onTapDown: (_) => _onTapDown(),
onTapUp: (_) => _onTapUp(),
onTapCancel: _onTapCancel,
child: Container(
color: Colors.transparent,
child: Stack(
alignment: Alignment.center,
children: [
AnimatedBuilder(
animation: _rippleAnimation,
builder: (context, child) {
return Container(
width: 60 * _rippleAnimation.value,
height: 60 * _rippleAnimation.value,
decoration: BoxDecoration(
shape: BoxShape.circle,
color:
Theme.of(context).colorScheme.primary.withOpacity(
0.1 * (1 - _rippleAnimation.value),
),
),
);
},
),
Column(
children: [
const SizedBox(height: 4),
AnimatedBuilder(
animation:
Listenable.merge([_scaleAnimation, _bounceAnimation]),
builder: (context, child) {
final scale = _scaleAnimation.value *
(widget.isSelected ? _bounceAnimation.value : 1.0);
return Transform.scale(
scale: scale,
child: AnimatedContainer(
padding:
EdgeInsets.all(widget.isHomeButton ? 8 : 4),
duration: DesignConfig.lowAnimationDuration,
decoration: BoxDecoration(
shape: BoxShape.circle,
color: widget.isSelected
? Theme.of(context)
.colorScheme
.primary
.withOpacity(0.1)
: Colors.transparent,
boxShadow: widget.isSelected
? [
BoxShadow(
color: Theme.of(context)
.colorScheme
.primary
.withOpacity(0.3),
blurRadius: 8,
spreadRadius: 1,
)
]
: null,
),
child: SizedBox(
width: widget.isHomeButton
? 50
: (widget.isSelected ? 50 : 32),
height: widget.isHomeButton
? 50
: (widget.isSelected ? 50 : 32),
child: AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
transitionBuilder: (child, animation) {
return ScaleTransition(
scale: animation,
child: RotationTransition(
turns: Tween<double>(begin: 0.8, end: 1.0)
.animate(animation),
child: child,
),
);
},
child: SvgPicture.asset(
widget.isSelected
? widget.selectedIconPath
: widget.unselectedIconPath,
key: ValueKey(widget.isSelected),
),
),
),
),
);
},
),
AnimatedSwitcher(
duration: const Duration(milliseconds: 200),
child: (!widget.isHomeButton && !widget.isSelected)
? AnimatedOpacity(
opacity: _isPressed ? 0.6 : 1.0,
duration: const Duration(milliseconds: 150),
child: DidvanText(
widget.title,
style: Theme.of(context).textTheme.bodySmall,
color: const Color.fromARGB(255, 102, 102, 102),
fontWeight: FontWeight.w500,
),
)
: const SizedBox.shrink(),
),
const Spacer(),
],
),
],
),
),
),
),
);
}
}