Skip to content

Commit 7b05d1a

Browse files
authored
Merge pull request #40 from splashbyte/version0.8.0
version 0.8.0-beta.5
2 parents 6c0c7ac + 138c944 commit 7b05d1a

10 files changed

Lines changed: 142 additions & 39 deletions

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.8.0-beta.5 (2023-08-18)
2+
3+
- fixes `AnimationType.onHover`
4+
15
## 0.8.0-beta.4 (2023-08-18)
26

37
- BREAKING: removes `IconTheme` for controlling default size of `Icon`s

example/lib/main.dart

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,7 @@ class _MyHomePageState extends State<MyHomePage> {
334334
),
335335
AnimatedToggleSwitch<int>.rolling(
336336
current: value,
337+
indicatorIconScale: sqrt2,
337338
values: const [0, 1, 2, 3],
338339
onChanged: (i) {
339340
setState(() => value = i);
@@ -350,10 +351,17 @@ class _MyHomePageState extends State<MyHomePage> {
350351
),
351352
AnimatedToggleSwitch<int?>.rolling(
352353
allowUnlistedValues: true,
354+
styleAnimationType: AnimationType.onHover,
353355
current: nullableValue,
354356
values: const [0, 1, 2, 3],
355357
onChanged: (i) => setState(() => nullableValue = i),
356358
iconBuilder: rollingIconBuilder,
359+
customStyleBuilder: (context, local, global) {
360+
final color = local.isValueListed
361+
? null
362+
: Theme.of(context).colorScheme.error;
363+
return ToggleStyle(borderColor: color, indicatorColor: color);
364+
},
357365
),
358366
Padding(
359367
padding: const EdgeInsets.all(8.0),

example/pubspec.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ packages:
77
path: ".."
88
relative: true
99
source: path
10-
version: "0.8.0-beta.3"
10+
version: "0.8.0-beta.5"
1111
async:
1212
dependency: transitive
1313
description:

lib/animated_toggle_switch.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ import 'package:flutter/foundation.dart';
88
import 'package:flutter/gestures.dart';
99
import 'package:flutter/material.dart';
1010

11+
part 'src/animation_type_builder.dart';
1112
part 'src/properties.dart';
1213
part 'src/style.dart';
14+
part 'src/tweens.dart';
1315
part 'src/cursors.dart';
1416
part 'src/foreground_indicator_transition.dart';
1517
part 'src/widgets/animated_toggle_switch.dart';
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
part of 'package:animated_toggle_switch/animated_toggle_switch.dart';
2+
3+
class _AnimationTypeHoverBuilder<T, V> extends StatefulWidget {
4+
final V Function(StyledToggleProperties<T> local) valueProvider;
5+
final V Function(V value1, V value2, double t) lerp;
6+
final Widget Function(V value) builder;
7+
final GlobalToggleProperties<T> properties;
8+
final Duration animationDuration;
9+
final Curve animationCurve;
10+
final Duration indicatorAppearingDuration;
11+
final Curve indicatorAppearingCurve;
12+
13+
const _AnimationTypeHoverBuilder({
14+
required this.valueProvider,
15+
required this.lerp,
16+
required this.builder,
17+
required this.properties,
18+
required this.animationDuration,
19+
required this.animationCurve,
20+
required this.indicatorAppearingDuration,
21+
required this.indicatorAppearingCurve,
22+
});
23+
24+
@override
25+
State<_AnimationTypeHoverBuilder<T, V>> createState() =>
26+
_AnimationTypeHoverBuilderState();
27+
}
28+
29+
class _AnimationTypeHoverBuilderState<T, V>
30+
extends State<_AnimationTypeHoverBuilder<T, V>> {
31+
final _builderKey = GlobalKey();
32+
T? _lastUnlistedValue;
33+
34+
@override
35+
void initState() {
36+
super.initState();
37+
if (!widget.properties.isCurrentListed) {
38+
_lastUnlistedValue = widget.properties.current;
39+
}
40+
}
41+
42+
@override
43+
void didUpdateWidget(covariant _AnimationTypeHoverBuilder<T, V> oldWidget) {
44+
super.didUpdateWidget(oldWidget);
45+
if (!widget.properties.isCurrentListed) {
46+
_lastUnlistedValue = widget.properties.current;
47+
}
48+
}
49+
50+
@override
51+
Widget build(BuildContext context) {
52+
final pos = widget.properties.position;
53+
final values = widget.properties.values;
54+
final index1 = pos.floor();
55+
final index2 = pos.ceil();
56+
final isListed = widget.properties.isCurrentListed;
57+
V listedValueFunction() => widget.lerp(
58+
widget.valueProvider(
59+
StyledToggleProperties(value: values[index1], index: index1)),
60+
widget.valueProvider(
61+
StyledToggleProperties(value: values[index2], index: index2)),
62+
pos - pos.floor(),
63+
);
64+
final unlistedDoubleValue = isListed ? 0.0 : 1.0;
65+
return TweenAnimationBuilder<double>(
66+
duration: widget.indicatorAppearingDuration,
67+
curve: widget.indicatorAppearingCurve,
68+
tween: Tween(begin: unlistedDoubleValue, end: unlistedDoubleValue),
69+
builder: (context, unlistedDoubleValue, _) {
70+
if (unlistedDoubleValue == 0.0) {
71+
return _EmptyWidget(
72+
key: _builderKey, child: widget.builder(listedValueFunction()));
73+
}
74+
final unlistedValue = widget.valueProvider(
75+
StyledToggleProperties(value: _lastUnlistedValue as T, index: -1));
76+
return TweenAnimationBuilder<V>(
77+
duration: widget.animationDuration,
78+
curve: widget.animationCurve,
79+
tween: _CustomTween(widget.lerp,
80+
begin: unlistedValue, end: unlistedValue),
81+
builder: (context, unlistedValue, _) {
82+
return _EmptyWidget(
83+
key: _builderKey,
84+
child: widget.builder(unlistedDoubleValue == 1.0
85+
? unlistedValue
86+
: widget.lerp(listedValueFunction(), unlistedValue,
87+
unlistedDoubleValue)),
88+
);
89+
});
90+
},
91+
);
92+
}
93+
}

lib/src/properties.dart

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ class GlobalToggleProperties<T> {
1616
/// If [values] does not contain [current], this value is set to [-1].
1717
final int currentIndex;
1818

19+
/// This value indicates if [values] does contain [current].
20+
bool get isCurrentListed => currentIndex >= 0;
21+
1922
/// The previous value of the switch.
2023
final T? previous;
2124

@@ -94,9 +97,12 @@ class LocalToggleProperties<T> {
9497

9598
/// The index of [value].
9699
///
97-
/// This value is [-1] if [values] does not contain [value].
100+
/// If [values] does not contain [value], this value is set to [-1].
98101
final int index;
99102

103+
/// This value indicates if [values] does contain [value].
104+
bool get isValueListed => index >= 0;
105+
100106
const LocalToggleProperties({
101107
required this.value,
102108
required this.index,

lib/src/tweens.dart

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
part of 'package:animated_toggle_switch/animated_toggle_switch.dart';
2+
3+
class _CustomTween<V> extends Tween<V> {
4+
final V Function(V value1, V value2, double t) lerpFunction;
5+
6+
_CustomTween(this.lerpFunction, {super.begin, super.end});
7+
8+
@override
9+
V lerp(double t) => lerpFunction(begin as V, end as V, t);
10+
}

lib/src/widgets/animated_toggle_switch.dart

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,14 +1064,10 @@ class AnimatedToggleSwitch<T> extends _AnimatedToggleSwitchParent<T> {
10641064
padding: EdgeInsets.all(borderWidth),
10651065
active: active,
10661066
wrapperBuilder: (context, global, child) {
1067-
return _ConditionalWrapper(
1068-
condition: inactiveOpacity < 1.0,
1069-
wrapper: (context, child) => AnimatedOpacity(
1070-
opacity: global.active ? 1.0 : inactiveOpacity,
1071-
duration: inactiveOpacityDuration,
1072-
curve: inactiveOpacityCurve,
1073-
child: child,
1074-
),
1067+
return AnimatedOpacity(
1068+
opacity: global.active ? 1.0 : inactiveOpacity,
1069+
duration: inactiveOpacityDuration,
1070+
curve: inactiveOpacityCurve,
10751071
child: _animationTypeBuilder<ToggleStyle>(
10761072
context,
10771073
styleAnimationType,
@@ -1110,7 +1106,6 @@ class AnimatedToggleSwitch<T> extends _AnimatedToggleSwitchParent<T> {
11101106
});
11111107
}
11121108

1113-
//TODO: extract this method to separate widget
11141109
Widget _animationTypeBuilder<V>(
11151110
BuildContext context,
11161111
AnimationType animationType,
@@ -1119,7 +1114,6 @@ class AnimatedToggleSwitch<T> extends _AnimatedToggleSwitchParent<T> {
11191114
Widget Function(V value) builder,
11201115
GlobalToggleProperties<T> properties,
11211116
) {
1122-
double pos = properties.position;
11231117
switch (animationType) {
11241118
case AnimationType.onSelected:
11251119
V currentValue = valueProvider(
@@ -1133,23 +1127,15 @@ class AnimatedToggleSwitch<T> extends _AnimatedToggleSwitchParent<T> {
11331127
builder: (context, value, _) => builder(value),
11341128
);
11351129
case AnimationType.onHover:
1136-
final index1 = pos.floor();
1137-
final index2 = pos.ceil();
1138-
final currentValue = properties.currentIndex < 0
1139-
? valueProvider(
1140-
StyledToggleProperties(value: properties.current, index: -1))
1141-
: lerp(
1142-
valueProvider(StyledToggleProperties(
1143-
value: values[index1], index: index1)),
1144-
valueProvider(StyledToggleProperties(
1145-
value: values[index2], index: index2)),
1146-
pos - pos.floor(),
1147-
);
1148-
return TweenAnimationBuilder<V>(
1149-
duration: animationDuration,
1150-
curve: animationCurve,
1151-
tween: _CustomTween(lerp, begin: currentValue, end: currentValue),
1152-
builder: (context, value, _) => builder(value),
1130+
return _AnimationTypeHoverBuilder(
1131+
valueProvider: valueProvider,
1132+
lerp: lerp,
1133+
builder: builder,
1134+
properties: properties,
1135+
animationDuration: animationDuration,
1136+
animationCurve: animationCurve,
1137+
indicatorAppearingDuration: indicatorAppearingDuration,
1138+
indicatorAppearingCurve: indicatorAppearingCurve,
11531139
);
11541140
}
11551141
}
@@ -1318,15 +1304,6 @@ class _MyLoading extends StatelessWidget {
13181304
}
13191305
}
13201306

1321-
class _CustomTween<V> extends Tween<V> {
1322-
final V Function(V value1, V value2, double t) lerpFunction;
1323-
1324-
_CustomTween(this.lerpFunction, {super.begin, super.end});
1325-
1326-
@override
1327-
V lerp(double t) => lerpFunction(begin as V, end as V, t);
1328-
}
1329-
13301307
extension _XTargetPlatform on TargetPlatform {
13311308
bool get isApple =>
13321309
this == TargetPlatform.iOS || this == TargetPlatform.macOS;

lib/src/widgets/conditional_wrapper.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
part of 'package:animated_toggle_switch/animated_toggle_switch.dart';
22

3+
// this widget is not covered because it is not used currently
4+
// coverage:ignore-start
35
class _ConditionalWrapper extends StatefulWidget {
46
final Widget Function(BuildContext context, Widget child) wrapper;
57
final bool condition;
@@ -25,6 +27,7 @@ class _ConditionalWrapperState extends State<_ConditionalWrapper> {
2527
return child;
2628
}
2729
}
30+
// coverage:ignore-end
2831

2932
class _EmptyWidget extends StatelessWidget {
3033
final Widget child;

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: animated_toggle_switch
22
description: Fully customizable, draggable and animated switch with multiple choices and smooth loading animation. It has prebuilt constructors for rolling and size animations.
3-
version: 0.8.0-beta.4
3+
version: 0.8.0-beta.5
44
repository: https://github.com/SplashByte/animated_toggle_switch
55
issue_tracker: https://github.com/SplashByte/animated_toggle_switch/issues
66

0 commit comments

Comments
 (0)