Skip to content

Commit

Permalink
adds parameters to AnimatedToggleSwitch
Browse files Browse the repository at this point in the history
adds innerGradient to AnimatedToggleSwitch and transitionType to all rolling AnimatedToggleSwitches
  • Loading branch information
maeddin committed Dec 22, 2022
1 parent 48ed82c commit 92404f6
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 49 deletions.
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
## 0.6.0 (2022-12-05)
## 0.6.0 (2022-12-22)
- fixes README
- fixes #28
- BREAKING: Increases minimum SDK to 2.17
- BREAKING: Renames `value` to `current` and `previousValue` to `previous` in `DetailedGlobalToggleProperties`
- BREAKING Feature: Adds loading animation to all switches. You can disable it by setting `loading` to false.
- Adds `innerGradient` to `AnimatedToggleSwitch`
- Adds `transitionType` to `AnimatedToggleSwitch.rolling`, `AnimatedToggleSwitch.rollingByHeight` and `AnimatedToggleSwitch.dual`

## 0.5.2 (2022-04-22)
- Minor performance improvement
Expand Down
7 changes: 5 additions & 2 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,8 @@ class _MyHomePageState extends State<MyHomePage> {
value = i;
loading = true;
});
return Future.delayed(Duration(seconds: 3)).then((_) => setState(()=>loading = false));
return Future.delayed(Duration(seconds: 3))
.then((_) => setState(() => loading = false));
},
iconBuilder: rollingIconBuilder,
borderColor: Colors.transparent,
Expand Down Expand Up @@ -144,7 +145,9 @@ class _MyHomePageState extends State<MyHomePage> {
onChanged: (i) => setState(() => value = i),
iconBuilder: rollingIconBuilder,
borderWidth: 4.5,
indicatorColor: Colors.purpleAccent,
indicatorColor: Colors.white,
innerGradient:
const LinearGradient(colors: [Colors.red, Colors.blue]),
innerColor: Colors.amber,
height: 55,
dif: 20.0,
Expand Down
2 changes: 1 addition & 1 deletion example/pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ packages:
path: ".."
relative: true
source: path
version: "0.5.2"
version: "0.6.0"
async:
dependency: transitive
description:
Expand Down
94 changes: 79 additions & 15 deletions lib/src/widgets/animated_toggle_switch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,35 @@ typedef IconBuilder<T> = Widget Function(BuildContext context,

typedef ColorBuilder<T> = Color? Function(T value);

enum AnimationType { onSelected, onHover }
/// Specifies when an icon should be highlighted.
enum AnimationType {
/// Starts an animation if an item is selected.
onSelected,

/// Start an animation if an item is hovered by the indicator.
onHover,
}

/// Different types of transitions for the foreground indicator.
///
/// Currently this enum is used only for deactivating the rolling animation in
/// some constructors.
enum ForegroundIndicatorTransitionType {
/// Fades between the different icons.
fading,

/// Fades between the different icons and shows a rolling animation
/// additionally.
rolling,
}

/// A class with different constructors of different switches.
/// The constructors have sensible default values for their parameters,
/// but can also be customized.
///
/// If you want to implement a completely custom switch,
/// you should use [CustomAnimatedToggleSwitch], which is used by
/// [AnimatedToggleSwitch] in the background.
class AnimatedToggleSwitch<T> extends StatelessWidget {
/// The currently selected value. It has to be set at [onChanged] or whenever for animating to this value.
///
Expand Down Expand Up @@ -83,6 +110,9 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
/// Color of the background.
final Color? innerColor;

/// Gradient of the background. Overwrites [innerColor] if not null.
final Gradient? innerGradient;

/// Opacity for the icons.
///
/// Please set [iconOpacity] and [selectedIconOpacity] to 1.0 for deactivating the AnimatedOpacity.
Expand Down Expand Up @@ -225,6 +255,7 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
this.loading,
this.loadingAnimationDuration,
this.loadingAnimationCurve,
this.innerGradient,
}) : this._iconArrangement = IconArrangement.row,
super(key: key);

Expand Down Expand Up @@ -276,6 +307,7 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
this.loading,
this.loadingAnimationDuration,
this.loadingAnimationCurve,
this.innerGradient,
}) : animatedIconBuilder = _iconSizeBuilder<T>(
iconBuilder, customIconBuilder, iconSize, selectedIconSize),
this._iconArrangement = IconArrangement.row,
Expand Down Expand Up @@ -330,6 +362,7 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
this.loading,
this.loadingAnimationDuration,
this.loadingAnimationCurve,
this.innerGradient,
}) : this.indicatorSize = indicatorSize * (height - 2 * borderWidth),
this.dif = dif * (height - 2 * borderWidth),
animatedIconBuilder = _iconSizeBuilder<T>(
Expand Down Expand Up @@ -413,6 +446,7 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
this.loading,
this.loadingAnimationDuration,
this.loadingAnimationCurve,
this.innerGradient,
}) : this.dif = dif * (height - 2 * borderWidth),
this.indicatorSize = indicatorSize * (height - 2 * borderWidth),
this._iconArrangement = IconArrangement.row,
Expand Down Expand Up @@ -468,6 +502,9 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
this.loading,
this.loadingAnimationDuration,
this.loadingAnimationCurve,
ForegroundIndicatorTransitionType transitionType =
ForegroundIndicatorTransitionType.rolling,
this.innerGradient,
}) : this.iconAnimationCurve = Curves.linear,
this.dif = dif * (height - 2 * borderWidth),
this.iconAnimationDuration = Duration.zero,
Expand All @@ -480,7 +517,8 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
iconBuilder,
customIconBuilder,
Size.square(
selectedIconRadius * 2 * (height - 2 * borderWidth))),
selectedIconRadius * 2 * (height - 2 * borderWidth)),
transitionType),
animatedIconBuilder = _standardIconBuilder(
iconBuilder,
customIconBuilder,
Expand Down Expand Up @@ -536,13 +574,20 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
this.loading,
this.loadingAnimationDuration,
this.loadingAnimationCurve,
ForegroundIndicatorTransitionType transitionType =
ForegroundIndicatorTransitionType.rolling,
this.innerGradient,
}) : this.iconAnimationCurve = Curves.linear,
this.iconAnimationDuration = Duration.zero,
this.selectedIconOpacity = iconOpacity,
this.iconAnimationType = AnimationType.onSelected,
this.foregroundIndicatorIconBuilder =
_rollingForegroundIndicatorIconBuilder<T>(values, iconBuilder,
customIconBuilder, Size.square(selectedIconRadius * 2)),
_rollingForegroundIndicatorIconBuilder<T>(
values,
iconBuilder,
customIconBuilder,
Size.square(selectedIconRadius * 2),
transitionType),
this.animatedIconBuilder = _standardIconBuilder(
iconBuilder,
customIconBuilder,
Expand All @@ -555,18 +600,22 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
List<T> values,
SimpleRollingIconBuilder<T>? iconBuilder,
RollingIconBuilder<T>? customIconBuilder,
Size iconSize) {
Size iconSize,
ForegroundIndicatorTransitionType transitionType) {
assert(iconBuilder == null || customIconBuilder == null);
if (customIconBuilder == null && iconBuilder != null)
customIconBuilder =
(c, l, g) => iconBuilder(l.value, l.iconSize, l.foreground);
return (context, global) {
if (customIconBuilder == null) return SizedBox();
double distance = global.dif + global.indicatorSize.width;
double angleDistance = distance /
iconSize.longestSide *
2 *
(global.textDirection == TextDirection.rtl ? -1.0 : 1.0);
double angleDistance =
transitionType == ForegroundIndicatorTransitionType.rolling
? distance /
iconSize.longestSide *
2 *
(global.textDirection == TextDirection.rtl ? -1.0 : 1.0)
: 0.0;
final pos = global.position;
int first = pos.floor();
double transitionValue = pos - first;
Expand Down Expand Up @@ -675,6 +724,9 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
this.loading,
this.loadingAnimationDuration,
this.loadingAnimationCurve,
ForegroundIndicatorTransitionType transitionType =
ForegroundIndicatorTransitionType.rolling,
this.innerGradient,
}) : assert(clipAnimation || opacityAnimation),
this.iconOpacity = 1.0,
this.selectedIconOpacity = 1.0,
Expand All @@ -687,7 +739,8 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
[first, second],
iconBuilder == null ? null : (v, s, f) => iconBuilder(v),
customIconBuilder,
Size.square(iconRadius * 2)),
Size.square(iconRadius * 2),
transitionType),
this.animatedIconBuilder = _dualIconBuilder(
textBuilder,
customTextBuilder,
Expand Down Expand Up @@ -821,7 +874,11 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
borderRadius: borderRadius,
),
decoration: BoxDecoration(
color: innerColor ?? theme.scaffoldBackgroundColor,
gradient: innerGradient,
// Redundant check
color: innerGradient != null
? null
: (innerColor ?? theme.scaffoldBackgroundColor),
borderRadius: borderRadius,
boxShadow: boxShadow,
),
Expand Down Expand Up @@ -934,9 +991,13 @@ class AnimatedToggleSwitch<T> extends StatelessWidget {
alignment: Alignment.center,
children: [
if (loadingValue < 1.0)
Opacity(opacity: 1.0 - loadingValue, child: child),
Opacity(
key: ValueKey(0),
opacity: 1.0 - loadingValue,
child: child),
if (loadingValue > 0.0)
Opacity(
key: ValueKey(1),
opacity: loadingValue,
child: loadingIconBuilder(context, global)),
],
Expand Down Expand Up @@ -989,9 +1050,12 @@ class _MyLoading extends StatelessWidget {

@override
Widget build(BuildContext context) {
return Theme.of(context).platform.apple
? CupertinoActivityIndicator()
: CircularProgressIndicator();
final color = Theme.of(context).iconTheme.color;
return Padding(
padding: const EdgeInsets.all(8.0),
child: Theme.of(context).platform.apple
? CupertinoActivityIndicator(color: color)
: CircularProgressIndicator(color: color));
}
}

Expand Down
35 changes: 5 additions & 30 deletions lib/src/widgets/custom_animated_toggle_switch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@ enum IconArrangement {
overlap
}

/// With this widget you can implement your own switches with nice animations.
///
/// For pre-made switches, please use the constructors of [AnimatedToggleSwitch]
/// instead.
class CustomAnimatedToggleSwitch<T> extends StatefulWidget {
/// The currently selected value. It has to be set at [onChanged] or whenever for animating to this value.
///
Expand Down Expand Up @@ -241,7 +245,7 @@ class _CustomAnimatedToggleSwitchState<T>

void _loading(bool b) {
if (b == _animationInfo.loading) return;
if(_animationInfo.toggleMode == ToggleMode.dragged) {
if (_animationInfo.toggleMode == ToggleMode.dragged) {
_animationInfo = _animationInfo.none();
_checkValuePosition();
}
Expand Down Expand Up @@ -662,35 +666,6 @@ class _WidgetPart extends StatelessWidget {
}
}

class _WidgetPartClipper extends CustomClipper<Rect> {
final double width, height;
final double left;

_WidgetPartClipper(
{this.width = double.infinity,
this.height = double.infinity,
required this.left});

@override
Rect getClip(Size size) => Rect.fromLTWH(left, 0, width, height);

@override
bool shouldReclip(covariant CustomClipper<Rect> oldClipper) =>
oldClipper != this;

@override
bool operator ==(Object other) =>
identical(this, other) ||
other is _WidgetPartClipper &&
runtimeType == other.runtimeType &&
width == other.width &&
height == other.height &&
left == other.left;

@override
int get hashCode => width.hashCode ^ height.hashCode ^ left.hashCode;
}

/// A class for holding the current state of [_CustomAnimatedToggleSwitchState].
class _AnimationInfo {
final double start;
Expand Down

0 comments on commit 92404f6

Please sign in to comment.