Skip to content

CupertinoButton inside ListView remains pressed after tapping and quickly dragging outside the button #165724

@jason-simmons

Description

@jason-simmons
  • Run the attached app
  • Tap on the button and quickly drag the pointer outside the bounds of the button

The button will continue rendering in the pressed state. It should instead revert to its original state after the pointer moves beyond the slop region or after the pointer is released.

This behavior regressed with #161731

The button's drag gesture and the ListView's drag gesture are both in the arena. After the pointer is dragged outside the button, the arena does a _resolveInFavorOf, selects the ListView gesture, and rejects the button gesture.

But BaseTapGestureRecognizer.rejectGesture does not cancel the tap because _sentTapDown is false. If the pointer was not inside the button long enough to send a tap down event, then rejectGesture does not send a cancel.

With #161731 the BaseTapGestureRecognizer is sending tap move events to the CupertinoButton. The CupertinoButton transitions to the pressed state based on the move events. If no cancel event is sent, then the button will remain pressed.

Code sample:

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        useMaterial3: false,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({Key? key, required this.title}) : super(key: key);
  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: ListView(
        children: <Widget>[
          CupertinoButton.filled(
            child: const Text('Test'),
            onPressed: () => print('onPressed'),
          ),
        ],
      ),
    );
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    c: regressionIt was better in the past than it is nowf: cupertinoflutter/packages/flutter/cupertino repositoryfound in release: 3.31Found to occur in 3.31frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onteam-designOwned by Design Languages team

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions