diff --git a/features/inspection/lib/presentation/root/view.dart b/features/inspection/lib/presentation/root/view.dart index b886a3f..4ce262b 100644 --- a/features/inspection/lib/presentation/root/view.dart +++ b/features/inspection/lib/presentation/root/view.dart @@ -12,37 +12,40 @@ class RootPage extends GetView { return Scaffold( body: Stack( children: [ - // سایر محتواها (مثلا صفحات اصلی) + Align( alignment: Alignment.bottomCenter, - child: Container( - height: 90, - color: AppColor.blueNormal, - clipBehavior: Clip.none, - padding: const EdgeInsets.all(10), - child: Stack( - clipBehavior: Clip.none, - alignment: Alignment.center, - children: [ - Positioned( - top: -43, - child: Container( - width: 110, - height: 110, - clipBehavior: Clip.none, - decoration: ShapeDecoration( - color:Colors.white, - - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(200), - side: BorderSide(width: 2, color: Colors.white), - ), - ), - ), - ), - WavePageView(), - ], - ), + child: WaveBottomNavigation( + items: [ + WaveBottomNavigationItem( + title: 'خانه', + icon:Assets.vecMapSvg, + ), + WaveBottomNavigationItem( + title: 'عملیات', + icon:Assets.vecUserSvg, + ), + WaveBottomNavigationItem( + title: 'افزودن', + icon:Assets.vecAddSvg, + ), + WaveBottomNavigationItem( + title: 'آمار', + icon:Assets.vecDiagramSvg, + ), WaveBottomNavigationItem( + title: 'تماس', + icon:Assets.vecCallSvg, + ), WaveBottomNavigationItem( + title: 'مکان ', + icon:Assets.vecGpsSvg, + ), WaveBottomNavigationItem( + title: 'تاریخ', + icon:Assets.vecCalendarSvg, + ), + ], + onPageChanged: (index) { + controller.changePage(index); + }, ), ), ], @@ -50,343 +53,3 @@ class RootPage extends GetView { ); } } - -class BottomNavigation1ItemTST extends StatelessWidget { - final String icon; - final String label; - final bool isSelected; - final Function() onTap; - - const BottomNavigation1ItemTST({ - super.key, - required this.icon, - required this.label, - required this.isSelected, - required this.onTap, - }); - - @override - Widget build(BuildContext context) { - return SizedBox( - width: 80, - height: 130, - child: Stack( - clipBehavior: Clip.none, - alignment: Alignment.bottomCenter, - children: [ - AnimatedPositioned( - duration: const Duration(milliseconds: 400), - width: 80, - height: 80, - bottom: isSelected ? 50 : 0, - child: InkWell( - splashColor: Colors.transparent, - onTap: onTap, - child: Container( - width: 80, - height: 80, - decoration: BoxDecoration( - color: isSelected ? AppColor.greenNormal : Colors.transparent, - borderRadius: BorderRadius.circular(40), - border: - isSelected - ? Border.all(width: 2, color: Colors.white) - : null, - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - vecWidget(icon, width: 32, height: 32, color: Colors.white), - const SizedBox(height: 7), - Text( - label, - style: AppFonts.yekan14.copyWith(color: Colors.white), - ), - ], - ), - ), - ), - ), - ], - ), - ); - } -} - -class ScrollWithCenterScaling extends StatefulWidget { - const ScrollWithCenterScaling({super.key}); - - @override - State createState() => - _ScrollWithCenterScalingState(); -} - -class _ScrollWithCenterScalingState extends State { - final PageController _pageController = PageController(viewportFraction: 0.3); - double currentPage = 0.0; - - @override - void initState() { - super.initState(); - _pageController.addListener(() { - setState(() { - currentPage = _pageController.page ?? 0.0; - }); - }); - } - - @override - void dispose() { - _pageController.dispose(); - super.dispose(); - } - - double _calculateScale(int index) { - final double distance = (currentPage - index).abs(); - if (distance >= 1) { - return 0.7; - } else { - return 1.3; - } - } - - bool _isSelected(int index) { - return (currentPage - index).abs() < 0.5; // دقیق وسط بودن رو بگیره - } - - @override - Widget build(BuildContext context) { - return PageView.builder( - controller: _pageController, - itemCount: 50, - clipBehavior: Clip.none, - physics: const BouncingScrollPhysics(), - scrollDirection: Axis.horizontal, - itemBuilder: (context, index) { - final scale = _calculateScale(index); - final selected = _isSelected(index); - - return Transform.scale( - scale: scale, - child: AnimatedPadding( - duration: const Duration(milliseconds: 300), - curve: Curves.easeOut, - padding: EdgeInsets.only(bottom: selected ? 20 : 0), - child: InkWell( - onTap: () {}, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.map, color: Colors.white), - const SizedBox(height: 8), - Text( - 'Label $index', - style: TextStyle( - color: Colors.white, - fontSize: selected ? 18 : 0, - fontWeight: - selected ? FontWeight.bold : FontWeight.normal, - ), - ), - ], - ), - ), - ), - ); - }, - ); - } -} - -class ScrollWithCenterRotation2 extends StatefulWidget { - const ScrollWithCenterRotation2({super.key}); - - @override - State createState() => - _ScrollWithCenterRotationState2(); -} - -class _ScrollWithCenterRotationState2 extends State { - final PageController _pageController = PageController(viewportFraction: 0.3); - double currentPage = 0.0; - - @override - void initState() { - super.initState(); - _pageController.addListener(() { - setState(() { - currentPage = _pageController.page ?? 0.0; - }); - }); - } - - @override - void dispose() { - _pageController.dispose(); - super.dispose(); - } - - double _calculateScale(int index) { - final double distance = (currentPage - index).abs(); - if (distance >= 1) { - return 0.7; - } else { - return 1.2; - } - } - - double _calculateRotationY(int index) { - return (currentPage - index) * 0.5; - } - - bool _isSelected(int index) { - return (currentPage - index).abs() < 0.5; - } - - @override - Widget build(BuildContext context) { - return PageView.builder( - controller: _pageController, - itemCount: 50, - clipBehavior: Clip.none, - physics: const BouncingScrollPhysics(), - scrollDirection: Axis.horizontal, - itemBuilder: (context, index) { - final scale = _calculateScale(index); - final rotationY = _calculateRotationY(index); - final selected = _isSelected(index); - - return AnimatedContainer( - clipBehavior: Clip.none, - height: 80, - duration: const Duration(milliseconds: 300), - curve: Curves.easeOut, - margin: EdgeInsets.only( - bottom: selected ? 90 : 20, // وسطی بالاتر میاد - ), - child: Transform( - transform: - Matrix4.identity() - ..scale(scale) - ..setEntry(3, 2, 0.001), - alignment: Alignment.center, - child: InkWell( - onTap: () {}, - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Container( - width: selected ? 70 : 60, - height: selected ? 70 : 60, - decoration: BoxDecoration( - color: Colors.red, - shape: BoxShape.circle, - boxShadow: - selected - ? [ - BoxShadow( - color: Colors.amber, - blurRadius: 20, - spreadRadius: 5, - ), - ] - : [], - ), - alignment: Alignment.center, - child: Icon( - Icons.map, - color: Colors.white, - size: selected ? 32 : 24, - ), - ), - const SizedBox(height: 8), - Text( - 'Label $index', - style: TextStyle( - color: Colors.white, - fontSize: selected ? 18 : 14, - fontWeight: - selected ? FontWeight.bold : FontWeight.normal, - ), - ), - ], - ), - ), - ), - ); - }, - ); - } -} - -class WavePageView extends StatefulWidget { - @override - _WavePageViewState createState() => _WavePageViewState(); -} - -class _WavePageViewState extends State { - final PageController _controller = PageController(viewportFraction: 0.3); - - @override - void dispose() { - _controller.dispose(); - super.dispose(); - } - double _calculateScale(double currentPage,int index) { - final double distance = (currentPage - index).abs(); - if (distance >= 1) { - return 0.7; - } else { - return 1.7; - } - } - - @override - Widget build(BuildContext context) { - return PageView.builder( - controller: _controller, - clipBehavior: Clip.none, - scrollDirection: Axis.horizontal, - itemCount: 10, - - itemBuilder: (context, index) { - return AnimatedBuilder( - animation: _controller, - builder: (context, child) { - double value = 0.0; - final scale = _calculateScale(_controller.page??0,index); - value = index - (_controller.page ?? 0); - value = (value).clamp(-1, 1); - - eLog("index = $index \n value = $value"); - - double offset = value * 30; - if (value.abs() < 0.1 || value.abs() > 0.1) { - offset = -5 * (1 - value.abs() * 5); - } - - return Transform.scale( - scale: scale, - child: Transform.translate( - offset: Offset(0, offset), - child: Column( - children: [ - Icon(Icons.map, color: value.toInt() == 0 ? AppColor.greenNormal:Colors.white, size: 32), - - Visibility( - visible: value.toInt() == 0, - child: Text( - 'بازرسی', - style: AppFonts.yekan10.copyWith(color: AppColor.greenNormal) - ), - ), - ], - ), - ), - ); - }, - ); - }, - ); - } -} diff --git a/packages/core/lib/presentation/widget/bottom_navigation/wave_bottom_navigation.dart b/packages/core/lib/presentation/widget/bottom_navigation/wave_bottom_navigation.dart new file mode 100644 index 0000000..95b808f --- /dev/null +++ b/packages/core/lib/presentation/widget/bottom_navigation/wave_bottom_navigation.dart @@ -0,0 +1,132 @@ +import 'package:flutter/material.dart'; +import 'package:rasadyar_core/core.dart'; + +class WaveBottomNavigationItem { + final String title; + final String icon; + + WaveBottomNavigationItem({required this.title, required this.icon}); +} + +class WaveBottomNavigation extends StatefulWidget { + const WaveBottomNavigation({ + super.key, + required this.items, + required this.onPageChanged, + }); + + final List items; + final Function(int) onPageChanged; + + @override + State createState() => _WaveBottomNavigationState(); +} + +class _WaveBottomNavigationState extends State { + final PageController _controller = PageController(viewportFraction: 0.3); + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + double _calculateScale(double currentPage, int index) { + final double distance = (currentPage - index).abs(); + if (distance >= 1) { + return 0.9; + } else { + return 1.50; + } + } + + @override + Widget build(BuildContext context) { + return Container( + height: 68, + color: AppColor.blueNormal, + clipBehavior: Clip.none, + padding: const EdgeInsets.all(10), + child: Stack( + clipBehavior: Clip.none, + alignment: Alignment.center, + children: [backgroundWidget(), waveScrolledLists()], + ), + ); + } + + Widget backgroundWidget() { + return Positioned( + top: -43, + child: Container( + width: 90, + height: 90, + clipBehavior: Clip.none, + decoration: ShapeDecoration( + color: AppColor.greenNormal, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(200), + side: BorderSide(width: 5, color: Colors.white), + ), + ), + ), + ); + } + + Widget waveScrolledLists() { + return PageView.builder( + controller: _controller, + clipBehavior: Clip.none, + onPageChanged: widget.onPageChanged, + scrollDirection: Axis.horizontal, + itemCount: widget.items.length, + physics: const ClampingScrollPhysics(), + itemBuilder: (context, index) { + final WaveBottomNavigationItem item = widget.items[index]; + return Center( + child: AnimatedBuilder( + animation: _controller, + builder: (context, child) { + double value = 0.0; + final scale = _calculateScale(_controller.page ?? 0, index); + value = index - (_controller.page ?? 0); + value = (value).clamp(-1, 1); + double offset = value * 30; + if (value.abs() < 0.2 || value.abs() > 0.2) { + offset = -7 * (1 - value.abs() * 2); + } + + return Transform.scale( + scale: scale, + child: Transform.translate( + offset: Offset(0, offset), + child: Column( + children: [ + Tooltip( + message: item.title, + child: vecWidget( + item.icon, + color: Colors.white, + width: 32, + height: 32, + ), + ), + + /* Visibility( + visible: (_controller.page ?? 0) == index, + child: Text( + item.title, + style: AppFonts.yekan10.copyWith(color: Colors.white), + ), + ),*/ + ], + ), + ), + ); + }, + ), + ); + }, + ); + } +} diff --git a/packages/core/lib/presentation/widget/widget.dart b/packages/core/lib/presentation/widget/widget.dart index 0df4a98..4f6869c 100644 --- a/packages/core/lib/presentation/widget/widget.dart +++ b/packages/core/lib/presentation/widget/widget.dart @@ -1,18 +1,16 @@ -export 'vec_widget.dart'; +export 'app_bar/r_app_bar.dart'; export 'bottom_navigation/bottom_navigation_1.dart'; +export 'bottom_navigation/wave_bottom_navigation.dart'; +export 'buttons/elevated.dart'; +export 'buttons/outline_elevated.dart'; +export 'buttons/outline_elevated_icon.dart'; +export 'buttons/text_button.dart'; +export 'captcha/captcha_widget.dart'; export 'draggable_bottom_sheet/draggable_bottom_sheet.dart'; export 'draggable_bottom_sheet/draggable_bottom_sheet_controller.dart'; -export 'buttons/outline_elevated_icon.dart'; -export 'buttons/outline_elevated.dart'; -export 'buttons/text_button.dart'; -export 'app_bar/r_app_bar.dart'; -export 'captcha/captcha_widget.dart'; -export 'buttons/elevated.dart'; export 'inputs/r_input.dart'; -export 'tabs/new_tab.dart'; -export 'tabs/tab.dart'; export 'pagination/pagination_from_until.dart'; export 'pagination/show_more.dart'; - - - +export 'tabs/new_tab.dart'; +export 'tabs/tab.dart'; +export 'vec_widget.dart';