From caa388424221558f29c18f51a532d9f34390b85a Mon Sep 17 00:00:00 2001 From: "mr.mojtaba" Date: Mon, 28 Apr 2025 17:06:21 +0330 Subject: [PATCH] feat : new bottom sheet V2 --- .../lib/presentation/root/view.dart | 331 ++++++++++++++++-- 1 file changed, 301 insertions(+), 30 deletions(-) diff --git a/features/inspection/lib/presentation/root/view.dart b/features/inspection/lib/presentation/root/view.dart index e81db3f..b886a3f 100644 --- a/features/inspection/lib/presentation/root/view.dart +++ b/features/inspection/lib/presentation/root/view.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:rasadyar_core/core.dart'; +import 'package:rasadyar_core/data/utils.dart'; import 'logic.dart'; @@ -14,39 +15,34 @@ class RootPage extends GetView { // سایر محتواها (مثلا صفحات اصلی) Align( alignment: Alignment.bottomCenter, - child: Column( - children: [ - const Spacer(), - Container( - height: 100, - padding: const EdgeInsets.symmetric(vertical: 10), - decoration: const BoxDecoration( - color: AppColor.blueNormal, - borderRadius: BorderRadius.vertical( - top: Radius.circular(40), - ), - ), - child: SingleChildScrollView( - clipBehavior: Clip.none, - scrollDirection: Axis.horizontal, - physics: const BouncingScrollPhysics(), - padding: const EdgeInsets.symmetric(horizontal: 10), - child: Row( - children: List.generate( - 50, - (index) => ObxValue((data) { - return BottomNavigation1ItemTST( - icon: Assets.vecMapSvg, - label: 'item$index', - isSelected: controller.currentIndex.value == index, - onTap: () => controller.changePage(index), - ); - }, controller.currentIndex), + 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(), + ], + ), ), ), ], @@ -117,5 +113,280 @@ class BottomNavigation1ItemTST extends StatelessWidget { } } +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) + ), + ), + ], + ), + ), + ); + }, + ); + }, + ); + } +}