Skip to content

Commit

Permalink
Merge pull request #42 from splashbyte/version0.8.0
Browse files Browse the repository at this point in the history
version 0.8.0-beta.6
  • Loading branch information
maeddin committed Aug 22, 2023
2 parents 7b05d1a + bca49e9 commit b6cf4dd
Show file tree
Hide file tree
Showing 15 changed files with 236 additions and 89 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 0.8.0-beta.6 (2023-08-22)

- adds parameter to `onTap` ([#41](https://github.com/splashbyte/animated_toggle_switch/issues/41))

## 0.8.0-beta.5 (2023-08-18)

- fixes `AnimationType.onHover`
Expand Down
2 changes: 1 addition & 1 deletion example/lib/crazy_switch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class _CrazySwitchState extends State<CrazySwitch> {
animationDuration: const Duration(milliseconds: 350),
animationCurve: Curves.bounceOut,
iconBuilder: (context, local, global) => const SizedBox(),
onTap: () => setState(() => current = !current),
onTap: (_) => setState(() => current = !current),
iconsTappable: false,
onChanged: (b) => setState(() => current = b),
height: height,
Expand Down
22 changes: 13 additions & 9 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,9 @@ class _MyHomePageState extends State<MyHomePage> {
colors: [green, Colors.red[800]!],
stops: [
global.position -
(1 - 2 * max(0, global.position - 0.5)) * 0.2,
(1 - 2 * max(0, global.position - 0.5)) * 0.7,
global.position +
max(0, 2 * (global.position - 0.5)) * 0.2,
max(0, 2 * (global.position - 0.5)) * 0.7,
],
));
},
Expand Down Expand Up @@ -269,7 +269,7 @@ class _MyHomePageState extends State<MyHomePage> {
Padding(
padding: const EdgeInsets.all(8.0),
child: Text(
'Switch inspired by package lite_rolling_switch',
'Switch similar to package lite_rolling_switch',
textAlign: TextAlign.center,
),
),
Expand Down Expand Up @@ -300,10 +300,7 @@ class _MyHomePageState extends State<MyHomePage> {
CupertinoActivityIndicator(
color: Color.lerp(
Colors.red[800], green, global.position)),
onChanged: (b) {
setState(() => positive = b);
return Future<dynamic>.delayed(Duration(seconds: 2));
},
onChanged: (b) => setState(() => positive = b),
iconBuilder: (value) => value
? Icon(Icons.power_outlined, color: green, size: 32.0)
: Icon(Icons.power_settings_new_rounded,
Expand Down Expand Up @@ -375,6 +372,7 @@ class _MyHomePageState extends State<MyHomePage> {
active: false,
current: value,
values: const [0, 1, 2, 3],
indicatorIconScale: sqrt2,
onChanged: (i) {
setState(() {
value = i;
Expand Down Expand Up @@ -423,6 +421,7 @@ class _MyHomePageState extends State<MyHomePage> {
)
],
),
indicatorIconScale: sqrt2,
iconBuilder: coloredRollingIconBuilder,
borderWidth: 3.0,
styleAnimationType: AnimationType.onHover,
Expand Down Expand Up @@ -457,7 +456,11 @@ class _MyHomePageState extends State<MyHomePage> {
current: nullableValue,
allowUnlistedValues: true,
values: const [0, 1, 2, 3],
onTap: () => setState(() => nullableValue = null),
onTap: (info) {
if (nullableValue == info.tapped?.value) {
setState(() => nullableValue = null);
}
},
onChanged: (i) => setState(() => nullableValue = i),
iconBuilder: rollingIconBuilder,
borderWidth: 4.5,
Expand Down Expand Up @@ -490,7 +493,7 @@ class _MyHomePageState extends State<MyHomePage> {
return const SizedBox();
},
cursors: ToggleCursors(defaultCursor: SystemMouseCursors.click),
onTap: () => setState(() => positive = !positive),
onTap: (_) => setState(() => positive = !positive),
iconsTappable: false,
wrapperBuilder: (context, global, child) {
return Stack(
Expand Down Expand Up @@ -703,6 +706,7 @@ class _MyHomePageState extends State<MyHomePage> {
current: value,
values: const [0, 1, 2, 3],
iconOpacity: 1.0,
selectedIconScale: 1.0,
indicatorSize: const Size.fromWidth(25),
foregroundIndicatorIconBuilder: (context, global) {
double pos = global.position;
Expand Down
3 changes: 2 additions & 1 deletion lib/animated_toggle_switch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,12 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';

part 'src/animation_type_builder.dart';
part 'src/animations.dart';
part 'src/properties.dart';
part 'src/style.dart';
part 'src/tweens.dart';
part 'src/cursors.dart';
part 'src/widgets/animation_type_builder.dart';
part 'src/foreground_indicator_transition.dart';
part 'src/widgets/animated_toggle_switch.dart';
part 'src/widgets/custom_animated_toggle_switch.dart';
Expand Down
36 changes: 36 additions & 0 deletions lib/src/animations.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
part of 'package:animated_toggle_switch/animated_toggle_switch.dart';

// this Animation is not covered because it does not contain logic but
// forwards all methods to its parent Animation.
// coverage:ignore-start
/// This class is a proxy for another animation.
///
/// It is used for passing animations in builders without exposing the real
/// animation to the user.
class _PrivateAnimation<T> extends Animation<T> {
final Animation<T> _parent;

_PrivateAnimation(this._parent);

@override
void addListener(VoidCallback listener) => _parent.addListener(listener);

@override
void addStatusListener(AnimationStatusListener listener) =>
_parent.addStatusListener(listener);

@override
void removeListener(VoidCallback listener) =>
_parent.removeListener(listener);

@override
void removeStatusListener(AnimationStatusListener listener) =>
_parent.removeStatusListener(listener);

@override
AnimationStatus get status => _parent.status;

@override
T get value => _parent.value;
}
// coverage:ignore-end
73 changes: 70 additions & 3 deletions lib/src/properties.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
// coverage:ignore-file
part of 'package:animated_toggle_switch/animated_toggle_switch.dart';

class ValueHolder<T> {
final T value;

/// The index of [value] in [values].
///
/// If [values] does not contain [value], this value is set to [-1].
final int index;

ValueHolder({required this.value, required this.index});
}

class GlobalToggleProperties<T> {
/// The position of the indicator relative to the indices of the values.
final double position;
Expand All @@ -13,7 +24,7 @@ class GlobalToggleProperties<T> {

/// The index of [current] in [values].
///
/// If [values] does not contain [current], this value is set to [-1].
/// If [values] does not contain [current], [currentIndex] is set to [-1].
final int currentIndex;

/// This value indicates if [values] does contain [current].
Expand Down Expand Up @@ -44,6 +55,17 @@ class GlobalToggleProperties<T> {

final bool active;

/// This animation indicates whether the indicator is currently visible.
///
/// [0.0] means it is not visible.
///
/// [1.0] means it is fully visible.
///
/// Depending on the curve of the animation, the value can also be below 0.0 or above 1.0.
///
/// This will be publicly accessible in future releases.
final Animation<double> _indicatorAppearingAnimation;

const GlobalToggleProperties({
required this.position,
required this.current,
Expand All @@ -55,7 +77,8 @@ class GlobalToggleProperties<T> {
required this.mode,
required this.loadingAnimationValue,
required this.active,
});
required Animation<double> indicatorAppearingAnimation,
}) : _indicatorAppearingAnimation = indicatorAppearingAnimation;
}

class DetailedGlobalToggleProperties<T> extends GlobalToggleProperties<T> {
Expand Down Expand Up @@ -88,6 +111,7 @@ class DetailedGlobalToggleProperties<T> extends GlobalToggleProperties<T> {
required super.mode,
required super.loadingAnimationValue,
required super.active,
required super.indicatorAppearingAnimation,
});
}

Expand All @@ -97,7 +121,7 @@ class LocalToggleProperties<T> {

/// The index of [value].
///
/// If [values] does not contain [value], this value is set to [-1].
/// If [values] does not contain [value], this [index] is set to [-1].
final int index;

/// This value indicates if [values] does contain [value].
Expand Down Expand Up @@ -181,3 +205,46 @@ class SeparatorProperties<T> {
required this.index,
});
}

class TapProperties<T> {
/// Information about the point on which the user has tapped.
///
/// This value can be [null] if the user taps on the border of an
/// [AnimatedToggleSwitch] or on the wrapper of a
/// [CustomAnimatedToggleSwitch].
final TapInfo<T>? tapped;

/// The values which are given to the switch.
///
/// Helpful if the list is generated e.g.
/// when the switch constructor is called.
final List<T> values;

const TapProperties({
required this.tapped,
required this.values,
});
}

class TapInfo<T> {
/// The value that the user has tapped.
final T value;

/// The index of [value] in [values].
///
/// [index == position.round()] should always be [true].
final int index;

/// The tapped position relative to the indices of the values.
///
/// [position] can be in the interval from [-0.5] to [values.length - 0.5].
///
/// [position.round() == index] should always be [true].
final double position;

TapInfo({
required this.value,
required this.index,
required this.position,
});
}
11 changes: 6 additions & 5 deletions lib/src/widgets/animated_toggle_switch.dart
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ abstract class _AnimatedToggleSwitchParent<T> extends StatelessWidget {
/// 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 _AnimatedToggleSwitchParent<T> {
class AnimatedToggleSwitch<T extends Object?>
extends _AnimatedToggleSwitchParent<T> {
/// The currently selected value. It has to be set at [onChanged] or whenever for animating to this value.
///
/// [current] has to be in [values] for working correctly if [allowUnlistedValues] is false.
Expand Down Expand Up @@ -168,7 +169,7 @@ class AnimatedToggleSwitch<T> extends _AnimatedToggleSwitchParent<T> {
final AnimationType indicatorAnimationType;

/// Callback for tapping anywhere on the widget.
final TapCallback? onTap;
final TapCallback<T>? onTap;

final IconArrangement _iconArrangement;

Expand Down Expand Up @@ -864,7 +865,7 @@ class AnimatedToggleSwitch<T> extends _AnimatedToggleSwitchParent<T> {
this.styleAnimationType = AnimationType.onHover,
this.indicatorAnimationType = AnimationType.onHover,
this.fittingMode = FittingMode.preventHorizontalOverlapping,
Function()? onTap,
TapCallback<T>? onTap,
this.minTouchTargetSize = 48.0,
this.textDirection,
this.cursors = const ToggleCursors(defaultCursor: SystemMouseCursors.click),
Expand Down Expand Up @@ -923,9 +924,9 @@ class AnimatedToggleSwitch<T> extends _AnimatedToggleSwitchParent<T> {
iconList: null,
);

static Function() _dualOnTap<T>(
static TapCallback<T> _dualOnTap<T>(
ChangeCallback<T>? onChanged, List<T> values, T? current) {
return () =>
return (info) =>
onChanged?.call(values.firstWhere((element) => element != current));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,20 @@ class _AnimationTypeHoverBuilderState<T, V>
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<double>(
duration: widget.indicatorAppearingDuration,
curve: widget.indicatorAppearingCurve,
tween: Tween(begin: unlistedDoubleValue, end: unlistedDoubleValue),
builder: (context, unlistedDoubleValue, _) {
if (unlistedDoubleValue == 0.0) {
final indicatorAppearingAnimation =
widget.properties._indicatorAppearingAnimation;
return AnimatedBuilder(
animation: indicatorAppearingAnimation,
builder: (context, _) {
final appearingValue = indicatorAppearingAnimation.value;
if (appearingValue >= 1.0) {
return _EmptyWidget(
key: _builderKey, child: widget.builder(listedValueFunction()));
}
Expand All @@ -81,10 +80,10 @@ class _AnimationTypeHoverBuilderState<T, V>
builder: (context, unlistedValue, _) {
return _EmptyWidget(
key: _builderKey,
child: widget.builder(unlistedDoubleValue == 1.0
child: widget.builder(appearingValue <= 0.0
? unlistedValue
: widget.lerp(listedValueFunction(), unlistedValue,
unlistedDoubleValue)),
: widget.lerp(
unlistedValue, listedValueFunction(), appearingValue)),
);
});
},
Expand Down
Loading

0 comments on commit b6cf4dd

Please sign in to comment.