Animate a CupertinoButton based on tap move events only if the move happens between a tap down and a tap up (#165729)

Fixes https://github.com/flutter/flutter/issues/165724
This commit is contained in:
Jason Simmons
2025-03-25 21:15:48 +00:00
committed by GitHub
parent cc845eb463
commit 0af426f37c
2 changed files with 31 additions and 3 deletions

View File

@@ -356,8 +356,10 @@ class _CupertinoButtonState extends State<CupertinoButton> with SingleTickerProv
}
bool _buttonHeldDown = false;
bool _tapInProgress = false;
void _handleTapDown(TapDownDetails event) {
_tapInProgress = true;
if (!_buttonHeldDown) {
_buttonHeldDown = true;
_animate();
@@ -365,6 +367,7 @@ class _CupertinoButtonState extends State<CupertinoButton> with SingleTickerProv
}
void _handleTapUp(TapUpDetails event) {
_tapInProgress = false;
if (_buttonHeldDown) {
_buttonHeldDown = false;
_animate();
@@ -377,19 +380,20 @@ class _CupertinoButtonState extends State<CupertinoButton> with SingleTickerProv
}
void _handleTapCancel() {
_tapInProgress = false;
if (_buttonHeldDown) {
_buttonHeldDown = false;
_animate();
}
}
void _handTapMove(TapMoveDetails event) {
void _handleTapMove(TapMoveDetails event) {
final RenderBox renderObject = context.findRenderObject()! as RenderBox;
final Offset localPosition = renderObject.globalToLocal(event.globalPosition);
final bool buttonShouldHeldDown = renderObject.paintBounds
.inflate(CupertinoButton.tapMoveSlop())
.contains(localPosition);
if (buttonShouldHeldDown != _buttonHeldDown) {
if (_tapInProgress && buttonShouldHeldDown != _buttonHeldDown) {
_buttonHeldDown = buttonShouldHeldDown;
_animate();
}
@@ -512,7 +516,7 @@ class _CupertinoButtonState extends State<CupertinoButton> with SingleTickerProv
instance.onTapDown = enabled ? _handleTapDown : null;
instance.onTapUp = enabled ? _handleTapUp : null;
instance.onTapCancel = enabled ? _handleTapCancel : null;
instance.onTapMove = enabled ? _handTapMove : null;
instance.onTapMove = enabled ? _handleTapMove : null;
instance.gestureSettings = gestureSettings;
},
),

View File

@@ -912,6 +912,30 @@ void main() {
expect(opacity.opacity.value, 0.4);
}, variant: TargetPlatformVariant.all());
testWidgets('Drag outside button within ListView does not leave the button pressed', (
WidgetTester tester,
) async {
await tester.pumpWidget(
boilerplate(
child: ListView(
children: <Widget>[CupertinoButton(onPressed: () {}, child: const Text('Tap me'))],
),
),
);
final FadeTransition opacity = tester.widget(
find.descendant(of: find.byType(CupertinoButton), matching: find.byType(FadeTransition)),
);
final TestGesture gesture = await tester.createGesture();
addTearDown(gesture.removePointer);
await gesture.down(tester.getTopLeft(find.byType(CupertinoButton)));
await gesture.moveBy(const Offset(1, 1));
await gesture.moveBy(Offset(0, -CupertinoButton.tapMoveSlop() - 5));
await tester.pumpAndSettle();
expect(opacity.opacity.value, 1.0);
});
testWidgets('onPressed trigger takes into account MoveSlop.', (WidgetTester tester) async {
bool value = false;
await tester.pumpWidget(