From 2c292d1324b6e2df2bf683fec16e687765771d2c Mon Sep 17 00:00:00 2001 From: ABDULLAH IBNA MUKTA <56233279+muktaahammed@users.noreply.github.com> Date: Fri, 11 Sep 2020 18:23:54 +0800 Subject: [PATCH] Create sidebar_with_scroll This side bar will help scrolling in all sizes screens --- lib/sidebar_with_scroll | 205 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 205 insertions(+) create mode 100644 lib/sidebar_with_scroll diff --git a/lib/sidebar_with_scroll b/lib/sidebar_with_scroll new file mode 100644 index 0000000..4c79285 --- /dev/null +++ b/lib/sidebar_with_scroll @@ -0,0 +1,205 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:rxdart/rxdart.dart'; +import '../bloc.navigation_bloc/navigation_bloc.dart'; +import '../sidebar/menu_item.dart'; + +class SideBar extends StatefulWidget { + @override + _SideBarState createState() => _SideBarState(); +} + +class _SideBarState extends State with SingleTickerProviderStateMixin { + AnimationController _animationController; + StreamController isSidebarOpenedStreamController; + Stream isSidebarOpenedStream; + StreamSink isSidebarOpenedSink; + final _animationDuration = const Duration(milliseconds: 500); + + @override + void initState() { + super.initState(); + _animationController = AnimationController(vsync: this, duration: _animationDuration); + isSidebarOpenedStreamController = PublishSubject(); + isSidebarOpenedStream = isSidebarOpenedStreamController.stream; + isSidebarOpenedSink = isSidebarOpenedStreamController.sink; + } + + @override + void dispose() { + _animationController.dispose(); + isSidebarOpenedStreamController.close(); + isSidebarOpenedSink.close(); + super.dispose(); + } + + void onIconPressed() { + final animationStatus = _animationController.status; + final isAnimationCompleted = animationStatus == AnimationStatus.completed; + + if (isAnimationCompleted) { + isSidebarOpenedSink.add(false); + _animationController.reverse(); + } else { + isSidebarOpenedSink.add(true); + _animationController.forward(); + } + } + + @override + Widget build(BuildContext context) { + final screenWidth = MediaQuery.of(context).size.width; + + return StreamBuilder( + initialData: false, + stream: isSidebarOpenedStream, + builder: (context, isSideBarOpenedAsync) { + return AnimatedPositioned( + duration: _animationDuration, + top: 0, + bottom: 0, + left: isSideBarOpenedAsync.data ? 0 : -screenWidth, + right: isSideBarOpenedAsync.data ? 0 : screenWidth - 45, + child: Row( + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 20), + color: const Color(0xFF262AAA), + child: SingleChildScrollView( + child: Column( + children: [ + SizedBox( + height: 100, + ), + ListTile( + title: Text( + "Prateek", + style: TextStyle(color: Colors.white, fontSize: 30, fontWeight: FontWeight.w800), + ), + subtitle: Text( + "www.techieblossom.com", + style: TextStyle( + color: Color(0xFF1BB5FD), + fontSize: 18, + ), + ), + leading: CircleAvatar( + child: Icon( + Icons.perm_identity, + color: Colors.white, + ), + radius: 40, + ), + ), + Divider( + height: 64, + thickness: 0.5, + color: Colors.white.withOpacity(0.3), + indent: 32, + endIndent: 32, + ), + MenuItem( + icon: Icons.home, + title: "Home", + onTap: () { + onIconPressed(); + BlocProvider.of(context).add(NavigationEvents.HomePageClickedEvent); + }, + ), + MenuItem( + icon: Icons.person, + title: "My Account", + onTap: () { + onIconPressed(); + BlocProvider.of(context).add(NavigationEvents.MyAccountClickedEvent); + }, + ), + MenuItem( + icon: Icons.shopping_basket, + title: "My Orders", + onTap: () { + onIconPressed(); + BlocProvider.of(context).add(NavigationEvents.MyOrdersClickedEvent); + }, + ), + MenuItem( + icon: Icons.card_giftcard, + title: "Wishlist", + ), + Divider( + height: 64, + thickness: 0.5, + color: Colors.white.withOpacity(0.3), + indent: 32, + endIndent: 32, + ), + MenuItem( + icon: Icons.settings, + title: "Settings", + ), + MenuItem( + icon: Icons.exit_to_app, + title: "Logout", + ), + ], + ), + ), + ), + ), + Align( + alignment: Alignment(0, -0.9), + child: GestureDetector( + onTap: () { + onIconPressed(); + }, + child: ClipPath( + clipper: CustomMenuClipper(), + child: Container( + width: 35, + height: 110, + color: Color(0xFF262AAA), + alignment: Alignment.centerLeft, + child: AnimatedIcon( + progress: _animationController.view, + icon: AnimatedIcons.menu_close, + color: Color(0xFF1BB5FD), + size: 25, + ), + ), + ), + ), + ), + ], + ), + ); + }, + ); + } +} + +class CustomMenuClipper extends CustomClipper { + @override + Path getClip(Size size) { + Paint paint = Paint(); + paint.color = Colors.white; + + final width = size.width; + final height = size.height; + + Path path = Path(); + path.moveTo(0, 0); + path.quadraticBezierTo(0, 8, 10, 16); + path.quadraticBezierTo(width - 1, height / 2 - 20, width, height / 2); + path.quadraticBezierTo(width + 1, height / 2 + 20, 10, height - 16); + path.quadraticBezierTo(0, height - 8, 0, height); + path.close(); + return path; + } + + @override + bool shouldReclip(CustomClipper oldClipper) { + return true; + } +}