Skip to content

Commit

Permalink
feat: Add onReleased action to AdvancedButtonComponent which will…
Browse files Browse the repository at this point in the history
… be called within `onTapUp` (#3152)

Add `onReleased` action which will be called within `onTapUp`. That
fixed some scenarios which require the pressed action to be called after
the user taps up the button.

For example, `AdvancedButtonComponent` doesn't show the `downSkin` if
the action of `onPressed` changes the router to another page. That is
because the router is changed before the `downSkin` is shown as the
`onPressed` action is called in `onTapDown`.
  • Loading branch information
mabdelaal86 committed May 10, 2024
1 parent 194d553 commit 2269732
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class AdvancedButtonComponent extends PositionComponent
with HoverCallbacks, TapCallbacks {
AdvancedButtonComponent({
this.onPressed,
this.onReleased,
this.onChangeState,
PositionComponent? defaultSkin,
PositionComponent? downSkin,
Expand Down Expand Up @@ -46,6 +47,9 @@ class AdvancedButtonComponent extends PositionComponent
/// Callback for what should happen when the button is pressed.
void Function()? onPressed;

/// Callback for what should happen when the button is released.
void Function()? onReleased;

/// Callback when button state changes
void Function(ButtonState state)? onChangeState;

Expand Down Expand Up @@ -93,8 +97,12 @@ class AdvancedButtonComponent extends PositionComponent

@override
void onTapUp(TapUpEvent event) {
if (_isDisabled) {
return;
}
isPressed = false;
updateState();
onReleased?.call();
}

@override
Expand Down
18 changes: 18 additions & 0 deletions packages/flame/test/components/advanced_button_component_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ void main() {

testWithFlameGame('correctly registers taps', (game) async {
var pressedTimes = 0;
var releasedTimes = 0;
final initialGameSize = Vector2.all(200);
final componentSize = Vector2.all(10);
final buttonPosition = Vector2.all(100);
Expand All @@ -35,16 +36,19 @@ void main() {
button = AdvancedButtonComponent(
defaultSkin: RectangleComponent(size: componentSize),
onPressed: () => pressedTimes++,
onReleased: () => releasedTimes++,
position: buttonPosition,
size: componentSize,
),
);

expect(pressedTimes, 0);
expect(releasedTimes, 0);
final tapDispatcher = game.firstChild<MultiTapDispatcher>()!;

tapDispatcher.handleTapDown(1, TapDownDetails());
expect(pressedTimes, 0);
expect(releasedTimes, 0);

tapDispatcher.handleTapUp(
1,
Expand All @@ -53,29 +57,34 @@ void main() {
),
);
expect(pressedTimes, 0);
expect(releasedTimes, 0);

tapDispatcher.handleTapDown(
1,
TapDownDetails(globalPosition: buttonPosition.toOffset()),
);
expect(pressedTimes, 1);
expect(releasedTimes, 0);

tapDispatcher.handleTapUp(
1,
createTapUpDetails(globalPosition: buttonPosition.toOffset()),
);
expect(pressedTimes, 1);
expect(releasedTimes, 1);

tapDispatcher.handleTapDown(
1,
TapDownDetails(globalPosition: buttonPosition.toOffset()),
);
tapDispatcher.handleTapCancel(1);
expect(pressedTimes, 2);
expect(releasedTimes, 1);
});

testWithFlameGame('correctly registers taps onGameResize', (game) async {
var pressedTimes = 0;
var releasedTimes = 0;
final initialGameSize = Vector2.all(100);
final componentSize = Vector2.all(10);
final buttonPosition = Vector2.all(100);
Expand All @@ -85,6 +94,7 @@ void main() {
button = AdvancedButtonComponent(
defaultSkin: RectangleComponent(size: componentSize),
onPressed: () => pressedTimes++,
onReleased: () => releasedTimes++,
position: buttonPosition,
size: componentSize,
),
Expand All @@ -99,23 +109,27 @@ void main() {
TapDownDetails(globalPosition: previousPosition),
);
expect(pressedTimes, 1);
expect(releasedTimes, 0);

tapDispatcher.handleTapUp(
1,
createTapUpDetails(globalPosition: previousPosition),
);
expect(pressedTimes, 1);
expect(releasedTimes, 1);

tapDispatcher.handleTapDown(
1,
TapDownDetails(globalPosition: previousPosition),
);
tapDispatcher.handleTapCancel(1);
expect(pressedTimes, 2);
expect(releasedTimes, 1);
});

testWithFlameGame('correctly work isDisabled', (game) async {
var pressedTimes = 0;
var releasedTimes = 0;
final initialGameSize = Vector2.all(100);
final componentSize = Vector2.all(10);
final buttonPosition = Vector2.all(100);
Expand All @@ -125,6 +139,7 @@ void main() {
button = AdvancedButtonComponent(
defaultSkin: RectangleComponent(size: componentSize),
onPressed: () => pressedTimes++,
onReleased: () => releasedTimes++,
position: buttonPosition,
size: componentSize,
),
Expand All @@ -140,19 +155,22 @@ void main() {
TapDownDetails(globalPosition: previousPosition),
);
expect(pressedTimes, 0);
expect(releasedTimes, 0);

tapDispatcher.handleTapUp(
1,
createTapUpDetails(globalPosition: previousPosition),
);
expect(pressedTimes, 0);
expect(releasedTimes, 0);

tapDispatcher.handleTapDown(
1,
TapDownDetails(globalPosition: previousPosition),
);
tapDispatcher.handleTapCancel(1);
expect(pressedTimes, 0);
expect(releasedTimes, 0);
});

testWidgets(
Expand Down

0 comments on commit 2269732

Please sign in to comment.