From 2269732e64a2acef2451d283c85b03e1101229ec Mon Sep 17 00:00:00 2001 From: Mohamed Abdelaal Date: Fri, 10 May 2024 20:34:31 +0200 Subject: [PATCH] feat: Add `onReleased` action to `AdvancedButtonComponent` which will 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`. --- .../input/advanced_button_component.dart | 8 ++++++++ .../advanced_button_component_test.dart | 18 ++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/packages/flame/lib/src/components/input/advanced_button_component.dart b/packages/flame/lib/src/components/input/advanced_button_component.dart index 62816180444..7deff4a1bb7 100644 --- a/packages/flame/lib/src/components/input/advanced_button_component.dart +++ b/packages/flame/lib/src/components/input/advanced_button_component.dart @@ -19,6 +19,7 @@ class AdvancedButtonComponent extends PositionComponent with HoverCallbacks, TapCallbacks { AdvancedButtonComponent({ this.onPressed, + this.onReleased, this.onChangeState, PositionComponent? defaultSkin, PositionComponent? downSkin, @@ -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; @@ -93,8 +97,12 @@ class AdvancedButtonComponent extends PositionComponent @override void onTapUp(TapUpEvent event) { + if (_isDisabled) { + return; + } isPressed = false; updateState(); + onReleased?.call(); } @override diff --git a/packages/flame/test/components/advanced_button_component_test.dart b/packages/flame/test/components/advanced_button_component_test.dart index d271ad313ee..b7bb452fb6a 100644 --- a/packages/flame/test/components/advanced_button_component_test.dart +++ b/packages/flame/test/components/advanced_button_component_test.dart @@ -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); @@ -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()!; tapDispatcher.handleTapDown(1, TapDownDetails()); expect(pressedTimes, 0); + expect(releasedTimes, 0); tapDispatcher.handleTapUp( 1, @@ -53,18 +57,21 @@ 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, @@ -72,10 +79,12 @@ void main() { ); 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); @@ -85,6 +94,7 @@ void main() { button = AdvancedButtonComponent( defaultSkin: RectangleComponent(size: componentSize), onPressed: () => pressedTimes++, + onReleased: () => releasedTimes++, position: buttonPosition, size: componentSize, ), @@ -99,12 +109,14 @@ 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, @@ -112,10 +124,12 @@ void main() { ); 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); @@ -125,6 +139,7 @@ void main() { button = AdvancedButtonComponent( defaultSkin: RectangleComponent(size: componentSize), onPressed: () => pressedTimes++, + onReleased: () => releasedTimes++, position: buttonPosition, size: componentSize, ), @@ -140,12 +155,14 @@ 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, @@ -153,6 +170,7 @@ void main() { ); tapDispatcher.handleTapCancel(1); expect(pressedTimes, 0); + expect(releasedTimes, 0); }); testWidgets(