From 4c879c333c9e789b249e24560c3a714ecf680a6c Mon Sep 17 00:00:00 2001 From: MaddinMade Date: Fri, 18 Aug 2023 13:18:43 +0200 Subject: [PATCH 1/5] version 0.8.0-beta.5 --- CHANGELOG.md | 4 + example/lib/main.dart | 200 ++++++++++++-------- example/pubspec.lock | 2 +- lib/animated_toggle_switch.dart | 2 + lib/src/animation_type_builder.dart | 85 +++++++++ lib/src/properties.dart | 9 +- lib/src/tweens.dart | 10 + lib/src/widgets/animated_toggle_switch.dart | 49 ++--- pubspec.yaml | 2 +- 9 files changed, 244 insertions(+), 119 deletions(-) create mode 100644 lib/src/animation_type_builder.dart create mode 100644 lib/src/tweens.dart diff --git a/CHANGELOG.md b/CHANGELOG.md index e6413a1..9c76b87 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.8.0-beta.5 (2023-08-18) + +- fixes `AnimationType.onHover` + ## 0.8.0-beta.4 (2023-08-18) - BREAKING: removes `IconTheme` for controlling default size of `Icon`s diff --git a/example/lib/main.dart b/example/lib/main.dart index 689ef99..eb8e2a2 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -78,10 +78,12 @@ class _MyHomePageState extends State { onChanged: (b) => setState(() => positive = b), styleBuilder: (b) => ToggleStyle(indicatorColor: b ? Colors.red : Colors.green), - iconBuilder: (value) => value + iconBuilder: (value) => + value ? Icon(Icons.coronavirus_rounded) : Icon(Icons.tag_faces_rounded), - textBuilder: (value) => value + textBuilder: (value) => + value ? Center(child: Text('Oh no...')) : Center(child: Text('Nice :)')), ), @@ -105,27 +107,32 @@ class _MyHomePageState extends State { borderWidth: 5.0, height: 55, onChanged: (b) => setState(() => positive = b), - styleBuilder: (b) => ToggleStyle( - backgroundColor: b ? Colors.white : Colors.black, - indicatorColor: b ? Colors.blue : Colors.red, - borderRadius: const BorderRadius.horizontal( - left: Radius.circular(4.0), right: Radius.circular(50.0)), - indicatorBorderRadius: BorderRadius.circular(b ? 50.0 : 4.0), - ), - iconBuilder: (value) => Icon( - value - ? Icons.access_time_rounded - : Icons.power_settings_new_rounded, - size: 32.0, - color: value ? Colors.black : Colors.white, - ), - textBuilder: (value) => value + styleBuilder: (b) => + ToggleStyle( + backgroundColor: b ? Colors.white : Colors.black, + indicatorColor: b ? Colors.blue : Colors.red, + borderRadius: const BorderRadius.horizontal( + left: Radius.circular(4.0), + right: Radius.circular(50.0)), + indicatorBorderRadius: BorderRadius.circular( + b ? 50.0 : 4.0), + ), + iconBuilder: (value) => + Icon( + value + ? Icons.access_time_rounded + : Icons.power_settings_new_rounded, + size: 32.0, + color: value ? Colors.black : Colors.white, + ), + textBuilder: (value) => + value ? const Center( - child: - Text('On', style: TextStyle(color: Colors.black))) + child: + Text('On', style: TextStyle(color: Colors.black))) : const Center( - child: - Text('Off', style: TextStyle(color: Colors.white))), + child: + Text('Off', style: TextStyle(color: Colors.white))), ), SizedBox(height: 16.0), DefaultTextStyle.merge( @@ -151,14 +158,14 @@ class _MyHomePageState extends State { return ToggleStyle(backgroundColor: Colors.red[800]); return ToggleStyle( backgroundGradient: LinearGradient( - colors: [green, Colors.red[800]!], - stops: [ - global.position - - (1 - 2 * max(0, global.position - 0.5)) * 0.2, - global.position + - max(0, 2 * (global.position - 0.5)) * 0.2, - ], - )); + colors: [green, Colors.red[800]!], + stops: [ + global.position - + (1 - 2 * max(0, global.position - 0.5)) * 0.2, + global.position + + max(0, 2 * (global.position - 0.5)) * 0.2, + ], + )); }, borderWidth: 6.0, height: 60.0, @@ -167,11 +174,13 @@ class _MyHomePageState extends State { color: Color.lerp( Colors.red[800], green, global.position)), onChanged: (b) => setState(() => positive = b), - iconBuilder: (value) => value + iconBuilder: (value) => + value ? Icon(Icons.power_outlined, color: green, size: 32.0) : Icon(Icons.power_settings_new_rounded, - color: Colors.red[800], size: 32.0), - textBuilder: (value) => value + color: Colors.red[800], size: 32.0), + textBuilder: (value) => + value ? Center(child: Text('Active')) : Center(child: Text('Inactive')), ), @@ -209,20 +218,23 @@ class _MyHomePageState extends State { borderWidth: 10.0, height: 50, loadingIconBuilder: (context, global) => - const CupertinoActivityIndicator(color: Colors.white), + const CupertinoActivityIndicator(color: Colors.white), onChanged: (b) { setState(() => positive = b); return Future.delayed(Duration(seconds: 2)); }, - styleBuilder: (b) => ToggleStyle( - indicatorColor: b ? Colors.purple : Colors.green), - iconBuilder: (value) => value + styleBuilder: (b) => + ToggleStyle( + indicatorColor: b ? Colors.purple : Colors.green), + iconBuilder: (value) => + value ? Icon(Icons.coronavirus_rounded) : Icon(Icons.tag_faces_rounded), - textBuilder: (value) => value + textBuilder: (value) => + value ? Center( - child: Text('Oh no...', - style: const TextStyle(color: Colors.white))) + child: Text('Oh no...', + style: const TextStyle(color: Colors.white))) : Center(child: Text('Nice :)')), ), ), @@ -240,8 +252,10 @@ class _MyHomePageState extends State { indicatorColor: Colors.white, backgroundColor: Colors.amber, ), - styleBuilder: (value) => ToggleStyle( - backgroundColor: value ? Colors.orange : Colors.red[800]), + styleBuilder: (value) => + ToggleStyle( + backgroundColor: value ? Colors.orange : Colors + .red[800]), borderWidth: 6.0, height: 60.0, loadingIconBuilder: (context, global) => @@ -252,19 +266,21 @@ class _MyHomePageState extends State { setState(() => positive = b); return Future.delayed(Duration(seconds: 2)); }, - iconBuilder: (value) => value + iconBuilder: (value) => + value ? Icon(Icons.power_outlined, - color: Colors.orange, size: 32.0) + color: Colors.orange, size: 32.0) : Icon(Icons.power_settings_new_rounded, - color: Colors.red[800], size: 32.0), - textBuilder: (value) => Center( - child: Text( - value ? 'Active' : 'Inactive', - style: const TextStyle( - color: Colors.white, - fontSize: 20.0, - fontWeight: FontWeight.w600), - )), + color: Colors.red[800], size: 32.0), + textBuilder: (value) => + Center( + child: Text( + value ? 'Active' : 'Inactive', + style: const TextStyle( + color: Colors.white, + fontSize: 20.0, + fontWeight: FontWeight.w600), + )), ), Padding( padding: const EdgeInsets.all(8.0), @@ -292,8 +308,9 @@ class _MyHomePageState extends State { indicatorColor: Colors.white, backgroundColor: Colors.black, ), - styleBuilder: (value) => ToggleStyle( - backgroundColor: value ? green : Colors.red[800]), + styleBuilder: (value) => + ToggleStyle( + backgroundColor: value ? green : Colors.red[800]), borderWidth: 6.0, height: 60.0, loadingIconBuilder: (context, global) => @@ -304,11 +321,13 @@ class _MyHomePageState extends State { setState(() => positive = b); return Future.delayed(Duration(seconds: 2)); }, - iconBuilder: (value) => value + iconBuilder: (value) => + value ? Icon(Icons.power_outlined, color: green, size: 32.0) : Icon(Icons.power_settings_new_rounded, - color: Colors.red[800], size: 32.0), - textBuilder: (value) => value + color: Colors.red[800], size: 32.0), + textBuilder: (value) => + value ? Center(child: Text('Active')) : Center(child: Text('Inactive')), ), @@ -350,10 +369,18 @@ class _MyHomePageState extends State { ), AnimatedToggleSwitch.rolling( allowUnlistedValues: true, + styleAnimationType: AnimationType.onHover, current: nullableValue, values: const [0, 1, 2, 3], onChanged: (i) => setState(() => nullableValue = i), iconBuilder: rollingIconBuilder, + customStyleBuilder: (context, local, global) { + final color = local.isValueListed ? null : Theme + .of(context) + .colorScheme + .error; + return ToggleStyle(borderColor: color, indicatorColor: color); + }, ), Padding( padding: const EdgeInsets.all(8.0), @@ -418,11 +445,13 @@ class _MyHomePageState extends State { iconBuilder: coloredRollingIconBuilder, borderWidth: 3.0, styleAnimationType: AnimationType.onHover, - styleBuilder: (value) => ToggleStyle( - backgroundColor: colorBuilder(value), - borderRadius: BorderRadius.circular(value * 10.0), - indicatorBorderRadius: BorderRadius.circular(value * 10.0), - ), + styleBuilder: (value) => + ToggleStyle( + backgroundColor: colorBuilder(value), + borderRadius: BorderRadius.circular(value * 10.0), + indicatorBorderRadius: BorderRadius.circular( + value * 10.0), + ), ), ), SizedBox(height: 16.0), @@ -456,7 +485,7 @@ class _MyHomePageState extends State { style: ToggleStyle( indicatorColor: Colors.white, backgroundGradient: - const LinearGradient(colors: [Colors.red, Colors.blue]), + const LinearGradient(colors: [Colors.red, Colors.blue]), borderColor: Colors.transparent, ), height: 55, @@ -499,7 +528,7 @@ class _MyHomePageState extends State { theme.colorScheme.background, global.position), borderRadius: - const BorderRadius.all(Radius.circular(50.0)), + const BorderRadius.all(Radius.circular(50.0)), ), )), child, @@ -540,8 +569,10 @@ class _MyHomePageState extends State { indicatorSize: const Size.fromWidth(100), iconAnimationType: AnimationType.onHover, styleAnimationType: AnimationType.onHover, - iconBuilder: (value) => Icon( - value.isEven ? Icons.cancel : Icons.access_time_rounded), + iconBuilder: (value) => + Icon( + value.isEven ? Icons.cancel : Icons + .access_time_rounded), style: ToggleStyle( borderColor: Colors.transparent, ), @@ -590,11 +621,13 @@ class _MyHomePageState extends State { values: const [false, true], iconOpacity: 0.2, indicatorSize: const Size.fromWidth(100), - customIconBuilder: (context, local, global) => Text( - local.value ? 'RAM' : 'CPU', - style: TextStyle( - color: Color.lerp( - Colors.black, Colors.white, local.animationValue))), + customIconBuilder: (context, local, global) => + Text( + local.value ? 'RAM' : 'CPU', + style: TextStyle( + color: Color.lerp( + Colors.black, Colors.white, + local.animationValue))), borderWidth: 4.0, iconAnimationType: AnimationType.onHover, style: ToggleStyle( @@ -638,8 +671,8 @@ class _MyHomePageState extends State { spacing: 2.0, customSeparatorBuilder: (context, local, global) { final opacity = - ((global.position - local.position).abs() - 0.5) - .clamp(0.0, 1.0); + ((global.position - local.position).abs() - 0.5) + .clamp(0.0, 1.0); return VerticalDivider( indent: 10.0, endIndent: 10.0, @@ -679,8 +712,9 @@ class _MyHomePageState extends State { ); }, style: ToggleStyle(borderColor: Colors.transparent), - styleBuilder: (i) => ToggleStyle( - indicatorColor: + styleBuilder: (i) => + ToggleStyle( + indicatorColor: i.isEven == true ? Colors.amber : Colors.red), onChanged: (i) => setState(() => value = i), ), @@ -716,8 +750,9 @@ class _MyHomePageState extends State { borderRadius: BorderRadius.all(Radius.circular(8.0)), indicatorBorderRadius: BorderRadius.zero, ), - styleBuilder: (i) => ToggleStyle( - indicatorColor: + styleBuilder: (i) => + ToggleStyle( + indicatorColor: i.isEven == true ? Colors.green : Colors.tealAccent), onChanged: (i) => setState(() => value = i), ), @@ -746,7 +781,10 @@ class _MyHomePageState extends State { indicatorSize: const Size.square(1.5), style: ToggleStyle(borderRadius: BorderRadius.circular(75.0)), ), - SizedBox(height: MediaQuery.of(context).padding.bottom + 16.0), + SizedBox(height: MediaQuery + .of(context) + .padding + .bottom + 16.0), ], ), ), // This trailing comma makes auto-formatting nicer for build methods. @@ -754,7 +792,8 @@ class _MyHomePageState extends State { ); } - Color colorBuilder(int value) => switch (value) { + Color colorBuilder(int value) => + switch (value) { 0 => Colors.blueAccent, 1 => Colors.green, 2 => Colors.orangeAccent, @@ -777,7 +816,8 @@ class _MyHomePageState extends State { return Icon(iconDataByValue(value)); } - IconData iconDataByValue(int? value) => switch (value) { + IconData iconDataByValue(int? value) => + switch (value) { 0 => Icons.access_time_rounded, 1 => Icons.check_circle_outline_rounded, 2 => Icons.power_settings_new_rounded, diff --git a/example/pubspec.lock b/example/pubspec.lock index 5578703..3b770ca 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -7,7 +7,7 @@ packages: path: ".." relative: true source: path - version: "0.8.0-beta.3" + version: "0.8.0-beta.5" async: dependency: transitive description: diff --git a/lib/animated_toggle_switch.dart b/lib/animated_toggle_switch.dart index 45044ad..5eca8b4 100644 --- a/lib/animated_toggle_switch.dart +++ b/lib/animated_toggle_switch.dart @@ -8,8 +8,10 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; +part 'src/animation_type_builder.dart'; part 'src/properties.dart'; part 'src/style.dart'; +part 'src/tweens.dart'; part 'src/cursors.dart'; part 'src/foreground_indicator_transition.dart'; part 'src/widgets/animated_toggle_switch.dart'; diff --git a/lib/src/animation_type_builder.dart b/lib/src/animation_type_builder.dart new file mode 100644 index 0000000..f75f807 --- /dev/null +++ b/lib/src/animation_type_builder.dart @@ -0,0 +1,85 @@ +part of 'package:animated_toggle_switch/animated_toggle_switch.dart'; + +class _AnimationTypeHoverBuilder extends StatefulWidget { + final V Function(StyledToggleProperties local) valueProvider; + final V Function(V value1, V value2, double t) lerp; + final Widget Function(V value) builder; + final GlobalToggleProperties properties; + final Duration animationDuration; + final Curve animationCurve; + final Duration indicatorAppearingDuration; + final Curve indicatorAppearingCurve; + + const _AnimationTypeHoverBuilder({ + required this.valueProvider, + required this.lerp, + required this.builder, + required this.properties, + required this.animationDuration, + required this.animationCurve, + required this.indicatorAppearingDuration, + required this.indicatorAppearingCurve, + }); + + @override + State<_AnimationTypeHoverBuilder> createState() => + _AnimationTypeHoverBuilderState(); +} + +class _AnimationTypeHoverBuilderState + extends State<_AnimationTypeHoverBuilder> { + final _builderKey = GlobalKey(); + T? _lastUnlistedValue; + + @override + void didUpdateWidget(covariant _AnimationTypeHoverBuilder oldWidget) { + super.didUpdateWidget(oldWidget); + if (!widget.properties.isCurrentListed) { + _lastUnlistedValue = widget.properties.current; + } + } + + @override + Widget build(BuildContext context) { + final pos = widget.properties.position; + final values = widget.properties.values; + final index1 = pos.floor(); + final index2 = pos.ceil(); + final isListed = widget.properties.isCurrentListed; + V listedValueFunction() => widget.lerp( + widget.valueProvider( + StyledToggleProperties(value: values[index1], index: index1)), + widget.valueProvider( + StyledToggleProperties(value: values[index2], index: index2)), + pos - pos.floor(), + ); + final unlistedDoubleValue = isListed ? 0.0 : 1.0; + return TweenAnimationBuilder( + duration: widget.indicatorAppearingDuration, + curve: widget.indicatorAppearingCurve, + tween: Tween(begin: unlistedDoubleValue, end: unlistedDoubleValue), + builder: (context, unlistedDoubleValue, _) { + if (unlistedDoubleValue == 0.0) { + return _EmptyWidget( + key: _builderKey, child: widget.builder(listedValueFunction())); + } + final unlistedValue = widget.valueProvider( + StyledToggleProperties(value: _lastUnlistedValue as T, index: -1)); + return TweenAnimationBuilder( + duration: widget.animationDuration, + curve: widget.animationCurve, + tween: _CustomTween(widget.lerp, + begin: unlistedValue, end: unlistedValue), + builder: (context, unlistedValue, _) { + return _EmptyWidget( + key: _builderKey, + child: widget.builder(unlistedDoubleValue == 1.0 + ? unlistedValue + : widget.lerp(listedValueFunction(), unlistedValue, + unlistedDoubleValue)), + ); + }); + }, + ); + } +} diff --git a/lib/src/properties.dart b/lib/src/properties.dart index 5bd68bf..f92cfec 100644 --- a/lib/src/properties.dart +++ b/lib/src/properties.dart @@ -16,6 +16,9 @@ class GlobalToggleProperties { /// If [values] does not contain [current], this value is set to [-1]. final int currentIndex; + /// This value indicates if [values] does contain [current]. + bool get isCurrentListed => currentIndex >= 0; + /// The previous value of the switch. final T? previous; @@ -94,9 +97,13 @@ class LocalToggleProperties { /// The index of [value]. /// - /// This value is [-1] if [values] does not contain [value]. + /// If [values] does not contain [value], this value is set to [-1]. final int index; + + /// This value indicates if [values] does contain [value]. + bool get isValueListed => index >= 0; + const LocalToggleProperties({ required this.value, required this.index, diff --git a/lib/src/tweens.dart b/lib/src/tweens.dart new file mode 100644 index 0000000..8a16d02 --- /dev/null +++ b/lib/src/tweens.dart @@ -0,0 +1,10 @@ +part of 'package:animated_toggle_switch/animated_toggle_switch.dart'; + +class _CustomTween extends Tween { + final V Function(V value1, V value2, double t) lerpFunction; + + _CustomTween(this.lerpFunction, {super.begin, super.end}); + + @override + V lerp(double t) => lerpFunction(begin as V, end as V, t); +} diff --git a/lib/src/widgets/animated_toggle_switch.dart b/lib/src/widgets/animated_toggle_switch.dart index 3b9d66b..10dd4ee 100644 --- a/lib/src/widgets/animated_toggle_switch.dart +++ b/lib/src/widgets/animated_toggle_switch.dart @@ -1064,14 +1064,10 @@ class AnimatedToggleSwitch extends _AnimatedToggleSwitchParent { padding: EdgeInsets.all(borderWidth), active: active, wrapperBuilder: (context, global, child) { - return _ConditionalWrapper( - condition: inactiveOpacity < 1.0, - wrapper: (context, child) => AnimatedOpacity( - opacity: global.active ? 1.0 : inactiveOpacity, - duration: inactiveOpacityDuration, - curve: inactiveOpacityCurve, - child: child, - ), + return AnimatedOpacity( + opacity: global.active ? 1.0 : inactiveOpacity, + duration: inactiveOpacityDuration, + curve: inactiveOpacityCurve, child: _animationTypeBuilder( context, styleAnimationType, @@ -1110,7 +1106,6 @@ class AnimatedToggleSwitch extends _AnimatedToggleSwitchParent { }); } - //TODO: extract this method to separate widget Widget _animationTypeBuilder( BuildContext context, AnimationType animationType, @@ -1119,7 +1114,6 @@ class AnimatedToggleSwitch extends _AnimatedToggleSwitchParent { Widget Function(V value) builder, GlobalToggleProperties properties, ) { - double pos = properties.position; switch (animationType) { case AnimationType.onSelected: V currentValue = valueProvider( @@ -1133,23 +1127,15 @@ class AnimatedToggleSwitch extends _AnimatedToggleSwitchParent { builder: (context, value, _) => builder(value), ); case AnimationType.onHover: - final index1 = pos.floor(); - final index2 = pos.ceil(); - final currentValue = properties.currentIndex < 0 - ? valueProvider( - StyledToggleProperties(value: properties.current, index: -1)) - : lerp( - valueProvider(StyledToggleProperties( - value: values[index1], index: index1)), - valueProvider(StyledToggleProperties( - value: values[index2], index: index2)), - pos - pos.floor(), - ); - return TweenAnimationBuilder( - duration: animationDuration, - curve: animationCurve, - tween: _CustomTween(lerp, begin: currentValue, end: currentValue), - builder: (context, value, _) => builder(value), + return _AnimationTypeHoverBuilder( + valueProvider: valueProvider, + lerp: lerp, + builder: builder, + properties: properties, + animationDuration: animationDuration, + animationCurve: animationCurve, + indicatorAppearingDuration: indicatorAppearingDuration, + indicatorAppearingCurve: indicatorAppearingCurve, ); } } @@ -1318,15 +1304,6 @@ class _MyLoading extends StatelessWidget { } } -class _CustomTween extends Tween { - final V Function(V value1, V value2, double t) lerpFunction; - - _CustomTween(this.lerpFunction, {super.begin, super.end}); - - @override - V lerp(double t) => lerpFunction(begin as V, end as V, t); -} - extension _XTargetPlatform on TargetPlatform { bool get isApple => this == TargetPlatform.iOS || this == TargetPlatform.macOS; diff --git a/pubspec.yaml b/pubspec.yaml index 1e6b5a6..8af5fa4 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: animated_toggle_switch description: Fully customizable, draggable and animated switch with multiple choices and smooth loading animation. It has prebuilt constructors for rolling and size animations. -version: 0.8.0-beta.4 +version: 0.8.0-beta.5 repository: https://github.com/SplashByte/animated_toggle_switch issue_tracker: https://github.com/SplashByte/animated_toggle_switch/issues From 6dca1371760cd98c119956e2ed102b24a01db727 Mon Sep 17 00:00:00 2001 From: MaddinMade Date: Fri, 18 Aug 2023 13:23:50 +0200 Subject: [PATCH 2/5] minor change --- example/lib/main.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/example/lib/main.dart b/example/lib/main.dart index eb8e2a2..51ce5dd 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -353,6 +353,7 @@ class _MyHomePageState extends State { ), AnimatedToggleSwitch.rolling( current: value, + indicatorIconScale: sqrt2, values: const [0, 1, 2, 3], onChanged: (i) { setState(() => value = i); From 430df5b38e467c61225fa00ba1457100c0162a0d Mon Sep 17 00:00:00 2001 From: MaddinMade Date: Fri, 18 Aug 2023 13:24:54 +0200 Subject: [PATCH 3/5] dart format --- example/lib/main.dart | 199 +++++++++++++++++----------------------- lib/src/properties.dart | 1 - 2 files changed, 83 insertions(+), 117 deletions(-) diff --git a/example/lib/main.dart b/example/lib/main.dart index 51ce5dd..a7b5a37 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -78,12 +78,10 @@ class _MyHomePageState extends State { onChanged: (b) => setState(() => positive = b), styleBuilder: (b) => ToggleStyle(indicatorColor: b ? Colors.red : Colors.green), - iconBuilder: (value) => - value + iconBuilder: (value) => value ? Icon(Icons.coronavirus_rounded) : Icon(Icons.tag_faces_rounded), - textBuilder: (value) => - value + textBuilder: (value) => value ? Center(child: Text('Oh no...')) : Center(child: Text('Nice :)')), ), @@ -107,32 +105,27 @@ class _MyHomePageState extends State { borderWidth: 5.0, height: 55, onChanged: (b) => setState(() => positive = b), - styleBuilder: (b) => - ToggleStyle( - backgroundColor: b ? Colors.white : Colors.black, - indicatorColor: b ? Colors.blue : Colors.red, - borderRadius: const BorderRadius.horizontal( - left: Radius.circular(4.0), - right: Radius.circular(50.0)), - indicatorBorderRadius: BorderRadius.circular( - b ? 50.0 : 4.0), - ), - iconBuilder: (value) => - Icon( - value - ? Icons.access_time_rounded - : Icons.power_settings_new_rounded, - size: 32.0, - color: value ? Colors.black : Colors.white, - ), - textBuilder: (value) => - value + styleBuilder: (b) => ToggleStyle( + backgroundColor: b ? Colors.white : Colors.black, + indicatorColor: b ? Colors.blue : Colors.red, + borderRadius: const BorderRadius.horizontal( + left: Radius.circular(4.0), right: Radius.circular(50.0)), + indicatorBorderRadius: BorderRadius.circular(b ? 50.0 : 4.0), + ), + iconBuilder: (value) => Icon( + value + ? Icons.access_time_rounded + : Icons.power_settings_new_rounded, + size: 32.0, + color: value ? Colors.black : Colors.white, + ), + textBuilder: (value) => value ? const Center( - child: - Text('On', style: TextStyle(color: Colors.black))) + child: + Text('On', style: TextStyle(color: Colors.black))) : const Center( - child: - Text('Off', style: TextStyle(color: Colors.white))), + child: + Text('Off', style: TextStyle(color: Colors.white))), ), SizedBox(height: 16.0), DefaultTextStyle.merge( @@ -158,14 +151,14 @@ class _MyHomePageState extends State { return ToggleStyle(backgroundColor: Colors.red[800]); return ToggleStyle( backgroundGradient: LinearGradient( - colors: [green, Colors.red[800]!], - stops: [ - global.position - - (1 - 2 * max(0, global.position - 0.5)) * 0.2, - global.position + - max(0, 2 * (global.position - 0.5)) * 0.2, - ], - )); + colors: [green, Colors.red[800]!], + stops: [ + global.position - + (1 - 2 * max(0, global.position - 0.5)) * 0.2, + global.position + + max(0, 2 * (global.position - 0.5)) * 0.2, + ], + )); }, borderWidth: 6.0, height: 60.0, @@ -174,13 +167,11 @@ class _MyHomePageState extends State { color: Color.lerp( Colors.red[800], green, global.position)), onChanged: (b) => setState(() => positive = b), - iconBuilder: (value) => - value + iconBuilder: (value) => value ? Icon(Icons.power_outlined, color: green, size: 32.0) : Icon(Icons.power_settings_new_rounded, - color: Colors.red[800], size: 32.0), - textBuilder: (value) => - value + color: Colors.red[800], size: 32.0), + textBuilder: (value) => value ? Center(child: Text('Active')) : Center(child: Text('Inactive')), ), @@ -218,23 +209,20 @@ class _MyHomePageState extends State { borderWidth: 10.0, height: 50, loadingIconBuilder: (context, global) => - const CupertinoActivityIndicator(color: Colors.white), + const CupertinoActivityIndicator(color: Colors.white), onChanged: (b) { setState(() => positive = b); return Future.delayed(Duration(seconds: 2)); }, - styleBuilder: (b) => - ToggleStyle( - indicatorColor: b ? Colors.purple : Colors.green), - iconBuilder: (value) => - value + styleBuilder: (b) => ToggleStyle( + indicatorColor: b ? Colors.purple : Colors.green), + iconBuilder: (value) => value ? Icon(Icons.coronavirus_rounded) : Icon(Icons.tag_faces_rounded), - textBuilder: (value) => - value + textBuilder: (value) => value ? Center( - child: Text('Oh no...', - style: const TextStyle(color: Colors.white))) + child: Text('Oh no...', + style: const TextStyle(color: Colors.white))) : Center(child: Text('Nice :)')), ), ), @@ -252,10 +240,8 @@ class _MyHomePageState extends State { indicatorColor: Colors.white, backgroundColor: Colors.amber, ), - styleBuilder: (value) => - ToggleStyle( - backgroundColor: value ? Colors.orange : Colors - .red[800]), + styleBuilder: (value) => ToggleStyle( + backgroundColor: value ? Colors.orange : Colors.red[800]), borderWidth: 6.0, height: 60.0, loadingIconBuilder: (context, global) => @@ -266,21 +252,19 @@ class _MyHomePageState extends State { setState(() => positive = b); return Future.delayed(Duration(seconds: 2)); }, - iconBuilder: (value) => - value + iconBuilder: (value) => value ? Icon(Icons.power_outlined, - color: Colors.orange, size: 32.0) + color: Colors.orange, size: 32.0) : Icon(Icons.power_settings_new_rounded, - color: Colors.red[800], size: 32.0), - textBuilder: (value) => - Center( - child: Text( - value ? 'Active' : 'Inactive', - style: const TextStyle( - color: Colors.white, - fontSize: 20.0, - fontWeight: FontWeight.w600), - )), + color: Colors.red[800], size: 32.0), + textBuilder: (value) => Center( + child: Text( + value ? 'Active' : 'Inactive', + style: const TextStyle( + color: Colors.white, + fontSize: 20.0, + fontWeight: FontWeight.w600), + )), ), Padding( padding: const EdgeInsets.all(8.0), @@ -308,9 +292,8 @@ class _MyHomePageState extends State { indicatorColor: Colors.white, backgroundColor: Colors.black, ), - styleBuilder: (value) => - ToggleStyle( - backgroundColor: value ? green : Colors.red[800]), + styleBuilder: (value) => ToggleStyle( + backgroundColor: value ? green : Colors.red[800]), borderWidth: 6.0, height: 60.0, loadingIconBuilder: (context, global) => @@ -321,13 +304,11 @@ class _MyHomePageState extends State { setState(() => positive = b); return Future.delayed(Duration(seconds: 2)); }, - iconBuilder: (value) => - value + iconBuilder: (value) => value ? Icon(Icons.power_outlined, color: green, size: 32.0) : Icon(Icons.power_settings_new_rounded, - color: Colors.red[800], size: 32.0), - textBuilder: (value) => - value + color: Colors.red[800], size: 32.0), + textBuilder: (value) => value ? Center(child: Text('Active')) : Center(child: Text('Inactive')), ), @@ -376,10 +357,9 @@ class _MyHomePageState extends State { onChanged: (i) => setState(() => nullableValue = i), iconBuilder: rollingIconBuilder, customStyleBuilder: (context, local, global) { - final color = local.isValueListed ? null : Theme - .of(context) - .colorScheme - .error; + final color = local.isValueListed + ? null + : Theme.of(context).colorScheme.error; return ToggleStyle(borderColor: color, indicatorColor: color); }, ), @@ -446,13 +426,11 @@ class _MyHomePageState extends State { iconBuilder: coloredRollingIconBuilder, borderWidth: 3.0, styleAnimationType: AnimationType.onHover, - styleBuilder: (value) => - ToggleStyle( - backgroundColor: colorBuilder(value), - borderRadius: BorderRadius.circular(value * 10.0), - indicatorBorderRadius: BorderRadius.circular( - value * 10.0), - ), + styleBuilder: (value) => ToggleStyle( + backgroundColor: colorBuilder(value), + borderRadius: BorderRadius.circular(value * 10.0), + indicatorBorderRadius: BorderRadius.circular(value * 10.0), + ), ), ), SizedBox(height: 16.0), @@ -486,7 +464,7 @@ class _MyHomePageState extends State { style: ToggleStyle( indicatorColor: Colors.white, backgroundGradient: - const LinearGradient(colors: [Colors.red, Colors.blue]), + const LinearGradient(colors: [Colors.red, Colors.blue]), borderColor: Colors.transparent, ), height: 55, @@ -529,7 +507,7 @@ class _MyHomePageState extends State { theme.colorScheme.background, global.position), borderRadius: - const BorderRadius.all(Radius.circular(50.0)), + const BorderRadius.all(Radius.circular(50.0)), ), )), child, @@ -570,10 +548,8 @@ class _MyHomePageState extends State { indicatorSize: const Size.fromWidth(100), iconAnimationType: AnimationType.onHover, styleAnimationType: AnimationType.onHover, - iconBuilder: (value) => - Icon( - value.isEven ? Icons.cancel : Icons - .access_time_rounded), + iconBuilder: (value) => Icon( + value.isEven ? Icons.cancel : Icons.access_time_rounded), style: ToggleStyle( borderColor: Colors.transparent, ), @@ -622,13 +598,11 @@ class _MyHomePageState extends State { values: const [false, true], iconOpacity: 0.2, indicatorSize: const Size.fromWidth(100), - customIconBuilder: (context, local, global) => - Text( - local.value ? 'RAM' : 'CPU', - style: TextStyle( - color: Color.lerp( - Colors.black, Colors.white, - local.animationValue))), + customIconBuilder: (context, local, global) => Text( + local.value ? 'RAM' : 'CPU', + style: TextStyle( + color: Color.lerp( + Colors.black, Colors.white, local.animationValue))), borderWidth: 4.0, iconAnimationType: AnimationType.onHover, style: ToggleStyle( @@ -672,8 +646,8 @@ class _MyHomePageState extends State { spacing: 2.0, customSeparatorBuilder: (context, local, global) { final opacity = - ((global.position - local.position).abs() - 0.5) - .clamp(0.0, 1.0); + ((global.position - local.position).abs() - 0.5) + .clamp(0.0, 1.0); return VerticalDivider( indent: 10.0, endIndent: 10.0, @@ -713,9 +687,8 @@ class _MyHomePageState extends State { ); }, style: ToggleStyle(borderColor: Colors.transparent), - styleBuilder: (i) => - ToggleStyle( - indicatorColor: + styleBuilder: (i) => ToggleStyle( + indicatorColor: i.isEven == true ? Colors.amber : Colors.red), onChanged: (i) => setState(() => value = i), ), @@ -751,9 +724,8 @@ class _MyHomePageState extends State { borderRadius: BorderRadius.all(Radius.circular(8.0)), indicatorBorderRadius: BorderRadius.zero, ), - styleBuilder: (i) => - ToggleStyle( - indicatorColor: + styleBuilder: (i) => ToggleStyle( + indicatorColor: i.isEven == true ? Colors.green : Colors.tealAccent), onChanged: (i) => setState(() => value = i), ), @@ -782,10 +754,7 @@ class _MyHomePageState extends State { indicatorSize: const Size.square(1.5), style: ToggleStyle(borderRadius: BorderRadius.circular(75.0)), ), - SizedBox(height: MediaQuery - .of(context) - .padding - .bottom + 16.0), + SizedBox(height: MediaQuery.of(context).padding.bottom + 16.0), ], ), ), // This trailing comma makes auto-formatting nicer for build methods. @@ -793,8 +762,7 @@ class _MyHomePageState extends State { ); } - Color colorBuilder(int value) => - switch (value) { + Color colorBuilder(int value) => switch (value) { 0 => Colors.blueAccent, 1 => Colors.green, 2 => Colors.orangeAccent, @@ -817,8 +785,7 @@ class _MyHomePageState extends State { return Icon(iconDataByValue(value)); } - IconData iconDataByValue(int? value) => - switch (value) { + IconData iconDataByValue(int? value) => switch (value) { 0 => Icons.access_time_rounded, 1 => Icons.check_circle_outline_rounded, 2 => Icons.power_settings_new_rounded, diff --git a/lib/src/properties.dart b/lib/src/properties.dart index f92cfec..773280f 100644 --- a/lib/src/properties.dart +++ b/lib/src/properties.dart @@ -100,7 +100,6 @@ class LocalToggleProperties { /// If [values] does not contain [value], this value is set to [-1]. final int index; - /// This value indicates if [values] does contain [value]. bool get isValueListed => index >= 0; From 0809937bd59655c6a335c95b89fa0c09d6434560 Mon Sep 17 00:00:00 2001 From: MaddinMade Date: Fri, 18 Aug 2023 13:35:27 +0200 Subject: [PATCH 4/5] fixes tests --- lib/src/animation_type_builder.dart | 8 ++++++++ lib/src/widgets/conditional_wrapper.dart | 3 +++ 2 files changed, 11 insertions(+) diff --git a/lib/src/animation_type_builder.dart b/lib/src/animation_type_builder.dart index f75f807..0448da2 100644 --- a/lib/src/animation_type_builder.dart +++ b/lib/src/animation_type_builder.dart @@ -31,6 +31,14 @@ class _AnimationTypeHoverBuilderState final _builderKey = GlobalKey(); T? _lastUnlistedValue; + @override + void initState() { + super.initState(); + if (!widget.properties.isCurrentListed) { + _lastUnlistedValue = widget.properties.current; + } + } + @override void didUpdateWidget(covariant _AnimationTypeHoverBuilder oldWidget) { super.didUpdateWidget(oldWidget); diff --git a/lib/src/widgets/conditional_wrapper.dart b/lib/src/widgets/conditional_wrapper.dart index 0c38c2b..836194c 100644 --- a/lib/src/widgets/conditional_wrapper.dart +++ b/lib/src/widgets/conditional_wrapper.dart @@ -1,5 +1,7 @@ +// not covered because this widget is not used currently part of 'package:animated_toggle_switch/animated_toggle_switch.dart'; +// coverage:ignore-start class _ConditionalWrapper extends StatefulWidget { final Widget Function(BuildContext context, Widget child) wrapper; final bool condition; @@ -25,6 +27,7 @@ class _ConditionalWrapperState extends State<_ConditionalWrapper> { return child; } } +// coverage:ignore-end class _EmptyWidget extends StatelessWidget { final Widget child; From 138c94416872dd407c22d8cecf50f97241e1ddb0 Mon Sep 17 00:00:00 2001 From: MaddinMade Date: Fri, 18 Aug 2023 13:36:01 +0200 Subject: [PATCH 5/5] minor change --- lib/src/widgets/conditional_wrapper.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/src/widgets/conditional_wrapper.dart b/lib/src/widgets/conditional_wrapper.dart index 836194c..88a02f1 100644 --- a/lib/src/widgets/conditional_wrapper.dart +++ b/lib/src/widgets/conditional_wrapper.dart @@ -1,6 +1,6 @@ -// not covered because this widget is not used currently part of 'package:animated_toggle_switch/animated_toggle_switch.dart'; +// this widget is not covered because it is not used currently // coverage:ignore-start class _ConditionalWrapper extends StatefulWidget { final Widget Function(BuildContext context, Widget child) wrapper;