diff options
author | Lisandro Pérez Meyer <lpmeyer@ics.com> | 2023-11-14 17:20:58 -0300 |
---|---|---|
committer | Lisandro Pérez Meyer <lpmeyer@ics.com> | 2023-11-14 17:31:12 -0300 |
commit | 70ec8a79a121471a004e7e4c23157d10157e136f (patch) | |
tree | a4f9c0a4fac4e4274ec4324a289b6ef62e1c5653 /lib/presentation/common_widget |
Initial cleanup push.
Based on agldemo2024 on commit 2a5dc04d801134338150c3f6afc67eaa65599763
Disable device preview.
Disable Lottie animation.
The original commit was b3c493c340fcb4bb0a937692838fc830bec3e9ea
but I am just keeping this change, because the json did not really
needed to change. I think.
Signed-off-by: Lisandro Pérez Meyer <lpmeyer@ics.com>
Diffstat (limited to 'lib/presentation/common_widget')
-rw-r--r-- | lib/presentation/common_widget/custom_bottom_bar.dart | 211 | ||||
-rw-r--r-- | lib/presentation/common_widget/custom_title.dart | 103 | ||||
-rw-r--r-- | lib/presentation/common_widget/custom_top_bar.dart | 106 | ||||
-rw-r--r-- | lib/presentation/common_widget/fan_bar.dart | 188 | ||||
-rw-r--r-- | lib/presentation/common_widget/generic_button.dart | 91 | ||||
-rw-r--r-- | lib/presentation/common_widget/settings_top_bar.dart | 37 | ||||
-rw-r--r-- | lib/presentation/common_widget/volume_and_fan_control.dart | 36 | ||||
-rw-r--r-- | lib/presentation/common_widget/volume_bar.dart | 356 |
8 files changed, 1128 insertions, 0 deletions
diff --git a/lib/presentation/common_widget/custom_bottom_bar.dart b/lib/presentation/common_widget/custom_bottom_bar.dart new file mode 100644 index 0000000..13084c0 --- /dev/null +++ b/lib/presentation/common_widget/custom_bottom_bar.dart @@ -0,0 +1,211 @@ +// ignore_for_file: prefer_const_constructors + +import '../../export.dart'; + +class CustomBottomBar extends ConsumerStatefulWidget { + const CustomBottomBar({super.key}); + + @override + CustomBottomBarState createState() => CustomBottomBarState(); +} + +class CustomBottomBarState extends ConsumerState<CustomBottomBar> { + @override + void initState() { + super.initState(); + // "ref" can be used in all life-cycles of a StatefulWidget. + //ref.read(counterProvider); + } + + double iconSize = 57; + List<BottomBarItems> navItems = [ + BottomBarItems(title: "Home", image: "Dashboard"), + BottomBarItems(title: "HVAC", image: "HVAC"), + BottomBarItems(title: "Media", image: "MediaPlayer"), + BottomBarItems(title: "Settings", image: "Settings"), + BottomBarItems(title: "Apps", image: "Apps") + ]; + String selectedNav = "Home"; + + void _onItemTapped(String title) { + AppState status = AppState.dashboard; + switch (title) { + case "Home": + status = AppState.dashboard; + case "HVAC": + status = AppState.hvac; + case "Media": + status = AppState.mediaPlayer; + case "Settings": + status = AppState.settings; + case "Apps": + status = AppState.apps; + } + setState(() { + selectedNav = title; + }); + + ref.read(appProvider.notifier).update((state) => state = status); + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(24.0), + child: Row( + children: navItems + .map((e) => Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + mainAxisSize: MainAxisSize.min, + children: [ + Container( + + margin: const EdgeInsets.symmetric( + horizontal: 2, + ), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + selectedNav == e.title + ? Color.fromARGB(217, 41, 98, 255) + : Color.fromARGB(163, 28, 46, 146), + selectedNav == e.title + ? Color.fromARGB(0, 41, 98, 255) + : Color.fromARGB(0, 41, 98, 255), + ], + stops: [ + selectedNav == e.title ? 0.3 : 0, + selectedNav == e.title ? 1 : 0.8, + ], + begin: Alignment.bottomCenter, + end: Alignment.topCenter), + // color: selectedNav == e + // ? AGLDemoColors.neonBlueColor + // : AGLDemoColors.buttonFillEnabledColor, + border: Border( + bottom: const BorderSide( + width: 1.0, + color: AGLDemoColors.jordyBlueColor), + ), + ), + child: Material( + color: Colors.transparent, + child: InkWell( + onTap: () { + _onItemTapped(e.title); + }, + child: Container( + padding: const EdgeInsets.symmetric(vertical: 7), + decoration: BoxDecoration( + border: Border( + left: selectedNav == e.title + ? const BorderSide(color: Colors.white30) + : BorderSide.none, + right: selectedNav == e.title + ? const BorderSide(color: Colors.white30) + : BorderSide.none, + // bottom: BorderSide( + // color: selectedNav == e.title + // ? Colors.white + // : Colors.white24, + // width: + // selectedNav == e.title ? 2 : 1) + )), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SvgPicture.asset( + "assets/${e.image}${selectedNav == e.title ? "Selected" : ""}.svg", + width: iconSize, + height: iconSize, + ), + Text( + e.title, + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 26, + shadows: [ + Shadow( + color: + Colors.black.withOpacity(0.7), + offset: Offset( + 1, + e.title == selectedNav + ? 1.5 + : 3), + blurRadius: e.title == selectedNav + ? 1 + : 3) + ], + color: e.title == selectedNav + ? Colors.white + : AGLDemoColors.periwinkleColor, + fontWeight: selectedNav == e.title + ? FontWeight.bold + : FontWeight.w300), + ), + ], + ), + ), + ), + ), + ), + //if (selectedNav == e.title) + Container( + margin: const EdgeInsets.symmetric(horizontal: 2), + color: selectedNav == e.title + ? Colors.white + : Colors.transparent, + height: 3, + ) + ], + ))) + .toList()), + ); + + // return Container( + // // decoration: const BoxDecoration( + // // gradient: LinearGradient( + // // begin: Alignment.topCenter, + // // end: Alignment.bottomCenter, + // // stops: [0.01, 1], + // // colors: <Color>[Colors.black, Color(0xFF1A237E)], + // // ), + // // ), + // //color: Color(0xFF0D113F), + // child: BottomNavigationBar( + // elevation: 0, + // showSelectedLabels: true, + // showUnselectedLabels: true, + // //backgroundColor: Colors.white, + // backgroundColor: const Color(0xFF0D113F), + // type: BottomNavigationBarType.fixed, + // items: const <BottomNavigationBarItem>[ + // BottomNavigationBarItem( + // icon: Icon(Icons.directions_car), + // label: 'Home', + // backgroundColor: Color(0xFF0D113F)), + // BottomNavigationBarItem(icon: Icon(Icons.ac_unit), label: 'HVAC'), + // BottomNavigationBarItem( + // icon: Icon(Icons.library_music), label: 'Media'), + // BottomNavigationBarItem( + // icon: Icon(Icons.settings), label: 'Settings'), + // BottomNavigationBarItem(icon: Icon(Icons.apps), label: 'Apps'), + // ], + // currentIndex: _selectedIndex, + // selectedItemColor: Colors.white, + // unselectedItemColor: Colors.grey, + + // onTap: _onItemTapped, + // ), + // ); + } +} + +class BottomBarItems { + final String title; + final String image; + + BottomBarItems({required this.title, required this.image}); +} diff --git a/lib/presentation/common_widget/custom_title.dart b/lib/presentation/common_widget/custom_title.dart new file mode 100644 index 0000000..f60c11e --- /dev/null +++ b/lib/presentation/common_widget/custom_title.dart @@ -0,0 +1,103 @@ +import 'package:flutter_ics_homescreen/export.dart'; + +class CommonTitle extends StatelessWidget { + const CommonTitle( + {super.key, + required this.title, + this.hasBackButton = false, + this.onPressed}); + + final String title; + final bool? hasBackButton; + final VoidCallback? onPressed; + + @override + Widget build(BuildContext context) { + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Padding( + padding: const EdgeInsets.only(top: 80), + child: SizedBox( + //color: Colors.amber, + height: 120, + child: Stack( + fit: StackFit.expand, + children: [ + Container( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.bottomCenter, + end: Alignment.center, + colors: [ + AGLDemoColors.jordyBlueColor.withOpacity(0.2), + AGLDemoColors.jordyBlueColor.withOpacity(0) + ], + stops: const [ + 0.0, + 1 + ])), + alignment: Alignment.center, + child: Text( + title, + textAlign: TextAlign.center, + style: const TextStyle( + color: Colors.white, + fontSize: 40, + fontWeight: FontWeight.w500), + ), + ), + if (hasBackButton!) + Align( + alignment: AlignmentDirectional.centerStart, + child: Padding( + padding: const EdgeInsets.only(left: 20.0), + child: InkWell( + customBorder: const CircleBorder(), + onTap: onPressed, + child: const Icon( + Icons.arrow_back, + color: Colors.white, + size: 48, + )), + ), + ), + ], + ), + ), + ), + Container( + height: 2, + decoration: BoxDecoration( + gradient: const LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + Colors.white10, + AGLDemoColors.jordyBlueColor, + Colors.white10 + ], + ), + boxShadow: [ + BoxShadow( + color: Colors.black.withOpacity(0.5), + blurRadius: 6, + spreadRadius: 3, + offset: const Offset(0, 6), + ), + ], + )), + Container( + height: 48, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Colors.black, Colors.black.withOpacity(0.0)], + ), + ), + ) + ], + ); + } +} diff --git a/lib/presentation/common_widget/custom_top_bar.dart b/lib/presentation/common_widget/custom_top_bar.dart new file mode 100644 index 0000000..c268f53 --- /dev/null +++ b/lib/presentation/common_widget/custom_top_bar.dart @@ -0,0 +1,106 @@ +import 'package:intl/intl.dart'; + +import '../../export.dart'; + +class CustomTopBar extends ConsumerStatefulWidget + implements PreferredSizeWidget { + const CustomTopBar({super.key}); + + @override + CustomTopBarState createState() => CustomTopBarState(); + + @override + Size get preferredSize => const Size.fromHeight(80); +} + +class CustomTopBarState extends ConsumerState<CustomTopBar> { + @override + Widget build(BuildContext context) { + final singnalsConnection = + ref.watch(signalsProvider.select((sinals) => sinals)); + final user = ref.watch(usersProvider.select((user) => user)); + final time2 = + ref.watch(dateTimeStateProvider.select((dateTime) => dateTime)); + + DateFormat dateFormat = DateFormat('HH:mm'); + //var time = dateFormat.format(DateTime.now()); + var time = time2.time; + + return AppBar( + elevation: 0, + backgroundColor: Colors.transparent, + //leadingWidth: 100, + + title: Stack( + //mainAxisAlignment: MainAxisAlignment.center, + children: [ + Positioned.fill( + child: Align( + alignment: Alignment.centerLeft, + child: Wrap( + children: [ + RichText( + text: TextSpan( + text: '$time ', + style: const TextStyle(color: Colors.white, fontSize: 26), + children: <InlineSpan>[ + const WidgetSpan( + child: SizedBox(width: 16), // 16px space + ), + TextSpan( + text: user.selectedUser.name, + style: const TextStyle(fontWeight: FontWeight.bold), + ), + ], + ), + ), + ], + ), + ), + ), + Align( + alignment: Alignment.center, + child: Image.asset( + 'assets/topBarLogo.png', + width: 659, + height: 56, + ), + ), + Positioned.fill( + child: Align( + alignment: Alignment.centerRight, + child: Wrap( + children: [ + Icon( + singnalsConnection.isBluetoothConnected + ? Icons.bluetooth + : Icons.bluetooth_disabled, + size: 24, + ), + const SizedBox( + width: 24, + ), + const Icon( + Icons.signal_cellular_4_bar_outlined, + size: 24, + ), + const SizedBox( + width: 24, + ), + Icon( + singnalsConnection.isWifiConnected + ? Icons.wifi + : Icons.wifi_off, + size: 24, + ), + ], + ), + ), + ), + ], + ), + + // ), + ); + } +} diff --git a/lib/presentation/common_widget/fan_bar.dart b/lib/presentation/common_widget/fan_bar.dart new file mode 100644 index 0000000..e119089 --- /dev/null +++ b/lib/presentation/common_widget/fan_bar.dart @@ -0,0 +1,188 @@ +import '../../export.dart'; +import 'package:flutter_ics_homescreen/presentation/custom_icons/custom_icons.dart'; + +enum FanMode { off, min, medium, max } + +class FanBar extends ConsumerStatefulWidget { + const FanBar({super.key}); + + @override + FanBarState createState() => FanBarState(); +} + +class FanBarState extends ConsumerState<FanBar> { + int selectedFanSpeed = 0; + + @override + Widget build(BuildContext context) { + final vehicle = ref.watch(vehicleProvider.select((vehicle) => vehicle)); + selectedFanSpeed = vehicle.fanSpeed; + + return Column(children: [ + Container( + padding: EdgeInsets.zero, + //width: 80, + height: 256, + decoration: const ShapeDecoration( + // gradient: RadialGradient( + // colors: [Color.fromARGB(255, 19, 24, 75), Colors.black], + // stops: [0, 0.9], + // radius: 1, + // ), + color: AGLDemoColors.buttonFillEnabledColor, + shape: StadiumBorder( + side: BorderSide( + color: Color(0xFF5477D4), + width: 1, + )), + ), + //alignment: Alignment.topLeft, + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Material( + color: Colors.transparent, + child: SizedBox( + width: 80, + height: 64, + child: IconButton( + isSelected: selectedFanSpeed == 3, + padding: EdgeInsets.zero, + color: AGLDemoColors.periwinkleColor, + onPressed: () { + ref.read(vehicleProvider.notifier).updateFanSpeed(3); + }, + icon: selectedFanSpeed == 3 + ? Stack( + alignment: Alignment.center, + children: [ + SvgPicture.asset('assets/fanButtonBg.svg'), + const Icon( + CustomIcons.fan_on_enabled, + color: Colors.white, + size: 40, + ), + ], + ) + : const Icon( + CustomIcons.fan_on_enabled, + size: 40, + ), + ), + ), + ), + Material( + color: Colors.transparent, + child: SizedBox( + width: 64, + height: 64, + child: IconButton( + isSelected: selectedFanSpeed == 2, + padding: EdgeInsets.zero, + color: AGLDemoColors.periwinkleColor, + onPressed: () { + ref.read(vehicleProvider.notifier).updateFanSpeed(2); + }, + icon: selectedFanSpeed == 2 + ? Stack( + alignment: Alignment.center, + children: [ + SvgPicture.asset('assets/fanButtonBg.svg'), + const Icon( + CustomIcons.fan_on_enabled, + color: Colors.white, + size: 28, + ), + ], + ) + : const Icon( + CustomIcons.fan_on_enabled, + size: 28, + ), + ), + ), + ), + Material( + color: Colors.transparent, + child: SizedBox( + width: 64, + height: 64, + child: IconButton( + isSelected: selectedFanSpeed == 1, + iconSize: 20, + padding: EdgeInsets.zero, + color: AGLDemoColors.periwinkleColor, + onPressed: () { + ref.read(vehicleProvider.notifier).updateFanSpeed(1); + }, + icon: selectedFanSpeed == 1 + ? Stack( + alignment: Alignment.center, + children: [ + SvgPicture.asset('assets/fanButtonBg.svg'), + const Icon( + CustomIcons.fan_on_enabled, + color: Colors.white, + size: 20, + ), + ], + ) + : const Icon( + CustomIcons.fan_on_enabled, + size: 20, + ), + ), + ), + ), + ], + ), + ), + const SizedBox(height: 10), + Container( + width: 80, + height: 80, + decoration: const ShapeDecoration( + // gradient: RadialGradient( + // colors: [Color.fromARGB(255, 19, 24, 75), Colors.black], + // stops: [0, 0.9], + // radius: 1, + // ), + color: AGLDemoColors.buttonFillEnabledColor, + shape: StadiumBorder( + side: BorderSide( + color: Color(0xFF5477D4), + width: 1, + )), + ), + //alignment: Alignment.topLeft, + child: Material( + color: Colors.transparent, + child: IconButton( + isSelected: selectedFanSpeed == 0, + padding: EdgeInsets.zero, + color: AGLDemoColors.periwinkleColor, + onPressed: () { + ref.read(vehicleProvider.notifier).updateFanSpeed(0); + }, + icon: selectedFanSpeed == 0 + ? Stack( + alignment: Alignment.center, + children: [ + SvgPicture.asset('assets/fanButtonBg.svg'), + const Icon( + Icons.mode_fan_off, + color: Colors.white, + size: 28.4, + ), + ], + ) + : const Icon( + Icons.mode_fan_off, + size: 28.4, + ), + ), + )), + ]); + } +} diff --git a/lib/presentation/common_widget/generic_button.dart b/lib/presentation/common_widget/generic_button.dart new file mode 100644 index 0000000..cca354f --- /dev/null +++ b/lib/presentation/common_widget/generic_button.dart @@ -0,0 +1,91 @@ +import 'package:flutter_ics_homescreen/export.dart'; + +class GenericButton extends StatefulWidget { + final double heigth; + final double width; + final String text; + final Function onTap; + + const GenericButton({ + super.key, + required this.heigth, + required this.width, + required this.text, + required this.onTap, + }); + + @override + State<GenericButton> createState() => _GenericButtonState(); +} + +class _GenericButtonState extends State<GenericButton> { + LinearGradient gradientEnable1 = const LinearGradient(colors: <Color>[ + Color(0xFF2962FF), + Color(0x802962FF), + ]); + LinearGradient gradientEnable2 = const LinearGradient(colors: <Color>[ + Color(0xFF1A237E), + Color(0xFF141F64), + ]); + @override + Widget build(BuildContext context) { + return GestureDetector( + onTapDown: (details) { + setState(() { + gradientEnable1 = const LinearGradient(colors: <Color>[ + Color(0x802962FF), + Color(0xFF2962FF), + ]); + gradientEnable2 = const LinearGradient(colors: <Color>[ + Color(0xFF1A237E), + Color(0xFF1C2D92), + ]); + }); + //change style + }, + onTapUp: (details) { + setState(() { + gradientEnable1 = const LinearGradient(colors: <Color>[ + Color(0xFF2962FF), + Color(0x802962FF), + ]); + gradientEnable2 = const LinearGradient(colors: <Color>[ + Color(0xFF1A237E), + Color(0xFF141F64), + ]); + }); + widget.onTap(); + }, + child: Container( + height: widget.heigth, + width: widget.width, + decoration: BoxDecoration( + gradient: Gradient.lerp(gradientEnable1, gradientEnable2, 0.5), + boxShadow: const [ + BoxShadow( + color: Colors.black, + blurRadius: 2, + offset: Offset(0, 2), // Shadow position + ), + ], + border: Border.all( + color: const Color(0xFF285DF4), + width: 1, + ), + borderRadius: const BorderRadius.all( + Radius.circular(4), + ), + ), + child: Center( + child: Text( + widget.text, + style: const TextStyle( + color: Color(0xFFC1D8FF), + fontSize: 44, + ), + ), + ), + ), + ); + } +} diff --git a/lib/presentation/common_widget/settings_top_bar.dart b/lib/presentation/common_widget/settings_top_bar.dart new file mode 100644 index 0000000..fb4e953 --- /dev/null +++ b/lib/presentation/common_widget/settings_top_bar.dart @@ -0,0 +1,37 @@ +import '../../export.dart'; + +class SettingsTopBar extends ConsumerStatefulWidget + implements PreferredSizeWidget { + final String title; + const SettingsTopBar(this.title, {super.key}); + + @override + SettingsTopBarState createState() => SettingsTopBarState(); + @override + Size get preferredSize => const Size.fromHeight(50); +} + +class SettingsTopBarState extends ConsumerState<SettingsTopBar> { + @override + Widget build( + BuildContext context, + ) { + return AppBar( + elevation: 0, + backgroundColor: const Color(0xFF0D113F), + leading: BackButton( + onPressed: () { + context.flow<AppState>().update((state) => AppState.settings); + }, + ), + title: Text( + widget.title, + style: const TextStyle( + fontStyle: FontStyle.normal, + fontWeight: FontWeight.normal, + fontSize: 20), + ), + //centerTitle: true, + ); + } +} diff --git a/lib/presentation/common_widget/volume_and_fan_control.dart b/lib/presentation/common_widget/volume_and_fan_control.dart new file mode 100644 index 0000000..051e360 --- /dev/null +++ b/lib/presentation/common_widget/volume_and_fan_control.dart @@ -0,0 +1,36 @@ +import '../common_widget/volume_bar.dart'; +import '../common_widget/fan_bar.dart'; + +import '../../export.dart'; + +class VolumeFanControl extends ConsumerWidget { + const VolumeFanControl({ + super.key, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final state = ref.watch(appProvider); + final size = MediaQuery.of(context).size; + final gapSize = size.height * 0.06; + + return Padding( + padding: const EdgeInsets.only(left: 10), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Visibility.maintain( + visible: state == AppState.mediaPlayer ? false : true, + child: const VolumeBar()), + SizedBox( + height: gapSize, + ), + Visibility.maintain( + visible: state == AppState.hvac ? false : true, + child: const FanBar(), + ), + ], + ), + ); + } +} diff --git a/lib/presentation/common_widget/volume_bar.dart b/lib/presentation/common_widget/volume_bar.dart new file mode 100644 index 0000000..a029698 --- /dev/null +++ b/lib/presentation/common_widget/volume_bar.dart @@ -0,0 +1,356 @@ +import 'package:flutter_ics_homescreen/presentation/custom_icons/custom_icons.dart'; + +import '../../export.dart'; + +class VolumeBar extends ConsumerStatefulWidget { + const VolumeBar({super.key}); + + @override + VolumeBarState createState() => VolumeBarState(); +} + +class VolumeBarState extends ConsumerState<VolumeBar> { + double val = 0; + @override + void initState() { + super.initState(); + // "ref" can be used in all life-cycles of a StatefulWidget. + //ref.read(counterProvider); + } + + void increaseVolume() { + setState(() { + if (val < 20) { + val++; + ref.read(audioStateProvider.notifier).setVolume(val); + } + }); + } + + void decreaseVolume() { + setState(() { + if (val > 0) { + val--; + ref.read(audioStateProvider.notifier).setVolume(val); + } + }); + } + + void setVolume(double newWalue) { + setState(() { + val = newWalue; + ref.read(audioStateProvider.notifier).setVolume(val); + }); + } + + void pause() {} + + @override + Widget build(BuildContext context) { + final volumeValue = + ref.watch(audioStateProvider.select((audio) => audio.volume)); + val = volumeValue; + return Column( + // mainAxisAlignment: MainAxisAlignment.center, + // crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Container( + width: 80, + height: 418, + //padding: const EdgeInsets.all(16), + decoration: const ShapeDecoration( + // gradient: RadialGradient( + // colors: [Color.fromARGB(255, 19, 24, 75), Colors.black], + // stops: [0, 0.9], + // radius: 1, + // ), + color: AGLDemoColors.buttonFillEnabledColor, + shape: StadiumBorder( + side: BorderSide( + color: Color(0xFF5477D4), + width: 1, + )), + ), + //alignment: Alignment.topLeft, + child: Column( + children: [ + SizedBox( + height: 68.0, + width: 56.0, + child: IconButton( + padding: EdgeInsets.zero, + color: AGLDemoColors.periwinkleColor, + onPressed: () { + increaseVolume(); + }, + icon: const Icon( + CustomIcons.vol_max, + size: 56, + ), + ), + ), + Padding( + padding: const EdgeInsets.only( + top: 4, bottom: 4), // Top and bottom padding + child: SizedBox( + height: 274.0, + child: RotatedBox( + quarterTurns: 3, + child: SliderTheme( + data: SliderTheme.of(context).copyWith( + activeTrackColor: AGLDemoColors.periwinkleColor, + inactiveTrackColor: const Color(0xFF0D113F), + trackShape: const GradinetRectangularSliderTrackShape(), + //trackShape: CustomTrackShape(), + trackHeight: 56.0, + //thumbColor: Colors.blueAccent, + thumbShape: const RectSliderThumbShape( + enabledThumbRadius: 0, disabledThumbRadius: 0), + //overlayColor: Colors.red.withAlpha(32), + overlayShape: + //RoundSliderOverlayShape(overlayRadius: 33.0), + //RoundSliderOverlayShape(overlayRadius: 0.0), + SliderComponentShape.noOverlay, + ), + child: Slider( + min: 0, + max: 20, + value: volumeValue, + divisions: 20, + onChanged: (newValue) { + setVolume(newValue); + }, + ), + ), + ), + ), + ), + SizedBox( + height: 56.0, + width: 56.0, + child: IconButton( + padding: EdgeInsets.zero, + color: AGLDemoColors.periwinkleColor, + onPressed: () { + decreaseVolume(); + }, + icon: const Icon( + CustomIcons.vol_min, + size: 56, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 10), + Container( + width: 80, + height: 80, + //padding: const EdgeInsets.all(16), + decoration: const ShapeDecoration( + // gradient: RadialGradient( + // colors: [Color.fromARGB(255, 19, 24, 75), Colors.black], + // stops: [0, 0.9], + // radius: 1, + // ), + color: AGLDemoColors.buttonFillEnabledColor, + shape: StadiumBorder( + side: BorderSide( + color: Color(0xFF5477D4), + width: 1, + )), + ), + //alignment: Alignment.topLeft, + child: IconButton( + padding: EdgeInsets.zero, + color: AGLDemoColors.periwinkleColor, + onPressed: () { + pause(); + }, + icon: const Icon( + Icons.pause, + size: 30, + )), + ), + ], + ); + } +} + +class RectSliderThumbShape extends SliderComponentShape { + /// Create a slider thumb that draws a Rect. + const RectSliderThumbShape({ + this.enabledThumbRadius = 10.0, + this.disabledThumbRadius, + this.elevation = 1.0, + this.pressedElevation = 6.0, + }); + + final double enabledThumbRadius; + + final double? disabledThumbRadius; + double get _disabledThumbRadius => disabledThumbRadius ?? enabledThumbRadius; + + final double elevation; + + final double pressedElevation; + + @override + Size getPreferredSize(bool isEnabled, bool isDiscrete) { + return Size.fromRadius( + isEnabled == true ? enabledThumbRadius : _disabledThumbRadius); + } + + @override + void paint( + PaintingContext context, + Offset center, { + required Animation<double> activationAnimation, + required Animation<double> enableAnimation, + required bool isDiscrete, + required TextPainter labelPainter, + required RenderBox parentBox, + required SliderThemeData sliderTheme, + required TextDirection textDirection, + required double value, + required double textScaleFactor, + required Size sizeWithOverflow, + }) { + final Canvas canvas = context.canvas; + + const Color color = Colors.white; + //const double radius = 0; + + final Tween<double> elevationTween = Tween<double>( + begin: elevation, + end: pressedElevation, + ); + + final double evaluatedElevation = + elevationTween.evaluate(activationAnimation); + + final Path path = Path() + ..addRect( + Rect.fromCenter( + center: Offset(center.dx - 3, center.dy + 2), width: 3, height: 54), + ); + + // canvas.drawRect( + // Rect.fromCenter(center: center, width: 4, height: 25), + // Paint()..color = color, + // ); + canvas.drawRect( + Rect.fromCenter(center: center, width: 4, height: 54), + Paint()..color = color, + ); + canvas.drawShadow(path, Colors.black, evaluatedElevation, true); + } +} + +class GradinetRectangularSliderTrackShape extends SliderTrackShape + with BaseSliderTrackShape { + /// Creates a slider track that draws 2 rectangles. + const GradinetRectangularSliderTrackShape(); + + @override + void paint( + PaintingContext context, + Offset offset, { + required RenderBox parentBox, + required SliderThemeData sliderTheme, + required Animation<double> enableAnimation, + required TextDirection textDirection, + required Offset thumbCenter, + Offset? secondaryOffset, + bool isDiscrete = false, + bool isEnabled = false, + }) { + assert(sliderTheme.disabledActiveTrackColor != null); + assert(sliderTheme.disabledInactiveTrackColor != null); + assert(sliderTheme.activeTrackColor != null); + assert(sliderTheme.inactiveTrackColor != null); + assert(sliderTheme.thumbShape != null); + // If the slider [SliderThemeData.trackHeight] is less than or equal to 0, + // then it makes no difference whether the track is painted or not, + // therefore the painting can be a no-op. + if (sliderTheme.trackHeight! <= 0) { + return; + } + + LinearGradient gradient = const LinearGradient( + colors: <Color>[ + //AGLDemoColors.periwinkleColor, + Color(0xff81A9ED), + Colors.white, + ], + ); + final Rect trackRect = getPreferredRect( + parentBox: parentBox, + offset: offset, + sliderTheme: sliderTheme, + isEnabled: isEnabled, + isDiscrete: isDiscrete, + ); + // Assign the track segment paints, which are left: active, right: inactive, + // but reversed for right to left text. + final ColorTween activeTrackColorTween = ColorTween( + begin: sliderTheme.disabledActiveTrackColor, + end: sliderTheme.activeTrackColor); + final ColorTween inactiveTrackColorTween = ColorTween( + begin: sliderTheme.disabledInactiveTrackColor, + end: sliderTheme.inactiveTrackColor); + final Paint activePaint = Paint() + ..shader = gradient.createShader(trackRect) + ..color = activeTrackColorTween.evaluate(enableAnimation)!; + final Paint inactivePaint = Paint() + ..color = inactiveTrackColorTween.evaluate(enableAnimation)!; + final Paint leftTrackPaint; + final Paint rightTrackPaint; + switch (textDirection) { + case TextDirection.ltr: + leftTrackPaint = activePaint; + rightTrackPaint = inactivePaint; + case TextDirection.rtl: + leftTrackPaint = inactivePaint; + rightTrackPaint = activePaint; + } + + final Rect leftTrackSegment = Rect.fromLTRB( + trackRect.left, trackRect.top, thumbCenter.dx, trackRect.bottom); + if (!leftTrackSegment.isEmpty) { + context.canvas.drawRect(leftTrackSegment, leftTrackPaint); + } + final Rect rightTrackSegment = Rect.fromLTRB( + thumbCenter.dx, trackRect.top, trackRect.right, trackRect.bottom); + if (!rightTrackSegment.isEmpty) { + context.canvas.drawRect(rightTrackSegment, rightTrackPaint); + } + + final bool showSecondaryTrack = (secondaryOffset != null) && + ((textDirection == TextDirection.ltr) + ? (secondaryOffset.dx > thumbCenter.dx) + : (secondaryOffset.dx < thumbCenter.dx)); + + if (showSecondaryTrack) { + final ColorTween secondaryTrackColorTween = ColorTween( + begin: sliderTheme.disabledSecondaryActiveTrackColor, + end: sliderTheme.secondaryActiveTrackColor); + final Paint secondaryTrackPaint = Paint() + ..color = secondaryTrackColorTween.evaluate(enableAnimation)!; + final Rect secondaryTrackSegment = Rect.fromLTRB( + (textDirection == TextDirection.ltr) + ? thumbCenter.dx + : secondaryOffset.dx, + trackRect.top, + (textDirection == TextDirection.ltr) + ? secondaryOffset.dx + : thumbCenter.dx, + trackRect.bottom, + ); + if (!secondaryTrackSegment.isEmpty) { + context.canvas.drawRect(secondaryTrackSegment, secondaryTrackPaint); + } + } + } +} |