Skip to content

The timing of the Haptic Feedback triggered by CupertinoPicker is incorrect. #169606

Open
@MrHeer

Description

@MrHeer

Steps to reproduce

Scroll CupertinoPicker and feel the Haptic Feedback on iPhone.

Expected results

Haptic Feedback should be triggered at the position where an item is selected.

BTW, the onSelectedItemChanged should get the value only when the scrolling settles, use a NotificationListener, listen for ScrollEndNotification and read its FixedExtentMetrics.(ref #92644)

Actual results

Haptic Feedback will be triggered at the mid-position between two items.

Code sample

Code sample
import 'package:flutter/cupertino.dart';

/// Flutter code sample for [CupertinoPicker].

const double _kItemExtent = 32.0;
const List<String> _fruitNames = <String>[
  'Apple',
  'Mango',
  'Banana',
  'Orange',
  'Pineapple',
  'Strawberry',
];

void main() => runApp(const CupertinoPickerApp());

class CupertinoPickerApp extends StatelessWidget {
  const CupertinoPickerApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const CupertinoApp(
      theme: CupertinoThemeData(brightness: Brightness.light),
      home: CupertinoPickerExample(),
    );
  }
}

class CupertinoPickerExample extends StatefulWidget {
  const CupertinoPickerExample({super.key});

  @override
  State<CupertinoPickerExample> createState() => _CupertinoPickerExampleState();
}

class _CupertinoPickerExampleState extends State<CupertinoPickerExample> {
  int _selectedFruit = 0;

  // This shows a CupertinoModalPopup with a reasonable fixed height which hosts CupertinoPicker.
  void _showDialog(Widget child) {
    showCupertinoModalPopup<void>(
      context: context,
      builder:
          (BuildContext context) => Container(
            height: 216,
            padding: const EdgeInsets.only(top: 6.0),
            // The Bottom margin is provided to align the popup above the system navigation bar.
            margin: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom),
            // Provide a background color for the popup.
            color: CupertinoColors.systemBackground.resolveFrom(context),
            // Use a SafeArea widget to avoid system overlaps.
            child: SafeArea(top: false, child: child),
          ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return CupertinoPageScaffold(
      navigationBar: const CupertinoNavigationBar(middle: Text('CupertinoPicker Sample')),
      child: DefaultTextStyle(
        style: TextStyle(color: CupertinoColors.label.resolveFrom(context), fontSize: 22.0),
        child: Center(
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text('Selected fruit: '),
              CupertinoButton(
                padding: EdgeInsets.zero,
                // Display a CupertinoPicker with list of fruits.
                onPressed:
                    () => _showDialog(
                      CupertinoPicker(
                        magnification: 1.22,
                        squeeze: 1.2,
                        useMagnifier: true,
                        itemExtent: _kItemExtent,
                        // This sets the initial item.
                        scrollController: FixedExtentScrollController(initialItem: _selectedFruit),
                        // This is called when selected item is changed.
                        onSelectedItemChanged: (int selectedItem) {
                          setState(() {
                            _selectedFruit = selectedItem;
                          });
                        },
                        children: List<Widget>.generate(_fruitNames.length, (int index) {
                          return Center(child: Text(_fruitNames[index]));
                        }),
                      ),
                    ),
                // This displays the selected fruit name.
                child: Text(_fruitNames[_selectedFruit], style: const TextStyle(fontSize: 22.0)),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    a: fidelityMatching the OEM platforms betterf: cupertinoflutter/packages/flutter/cupertino repositoryfound in release: 3.32Found to occur in 3.32found in release: 3.33Found to occur in 3.33frameworkflutter/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