Skip to content

CupertinoPicker should report item change only on scroll end #170201

@alex-medinsh

Description

@alex-medinsh

This is a continuation of #169606

Steps to reproduce

Scroll the picker over multiple items.

Expected results

Native picker only reports the change when the scroll settles.

Actual results

onSelectedItemChanged is called every time a new item is scrolled over.

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)),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Screenshots or Video

Screenshots / Video demonstration

[Upload media here]

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
[!] Flutter (Channel [user-branch], 3.33.0-1.0.pre.417, on macOS 15.5 24F74 darwin-arm64, locale en-GB) [8.3s]
    ! Flutter version 3.33.0-1.0.pre.417 on channel [user-branch] at /Users/alex/workspace/flutter_fork
      Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
      If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/setup.
    ! Upstream repository https://github.com/flutter/flutter.git/ is not a standard remote.
      Set environment variable "FLUTTER_GIT_URL" to https://github.com/flutter/flutter.git/ to dismiss this error.
    • Framework revision e9e989bef3 (5 hours ago), 2025-06-07 07:45:31 -0400
    • Engine revision e9e989bef3
    • Dart version 3.9.0 (build 3.9.0-211.0.dev)
    • DevTools version 2.48.0-dev.0
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and
      upgrades.

[✓] Android toolchain - develop for Android devices (Android SDK version 35.0.0) [2.1s]
    • Android SDK at /Users/alex/Library/Android/sdk
    • Emulator version 35.2.10.0 (build_id 12414864) (CL:N/A)
    • Platform android-36, build-tools 35.0.0
    • ANDROID_HOME = /Users/alex/Library/Android/sdk
    • Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
      This is the JDK bundled with the latest Android Studio installation on this machine.
      To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
    • Java version OpenJDK Runtime Environment (build 21.0.3+-79915917-b509.11)
    • All Android licenses accepted.

[!] Xcode - develop for iOS and macOS (Xcode 16.4) [1,360ms]
    • Xcode at /Applications/Xcode.app/Contents/Developer
    • Build 16F6
    ! CocoaPods 1.13.0 out of date (1.16.2 is recommended).
        CocoaPods is a package manager for iOS or macOS platform code.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/to/platform-plugins
      To update CocoaPods, see https://guides.cocoapods.org/using/getting-started.html#updating-cocoapods

[✗] Chrome - develop for the web (Cannot find Chrome executable at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome) [13ms]
    ! Cannot find Chrome. Try setting CHROME_EXECUTABLE to a Chrome executable.

[✓] Android Studio (version 2024.2) [12ms]
    • Android Studio at /Applications/Android Studio.app/Contents
    • Flutter plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/9212-flutter
    • Dart plugin can be installed from:
      🔨 https://plugins.jetbrains.com/plugin/6351-dart
    • Java version OpenJDK Runtime Environment (build 21.0.3+-79915917-b509.11)

[✓] VS Code (version 1.100.3) [10ms]
    • VS Code at /Applications/Visual Studio Code.app/Contents
    • Flutter extension version 3.112.0

[✓] Connected device (3 available) [7.0s]
    • Alex’s iPhone (wireless) (mobile) • 00008130-001A310C0491401C            • ios          • iOS 18.5 22F76
    • iPhone 16 Pro (mobile)            • CA350618-1F12-428B-ABB3-9D688B09D1F4 • ios          • com.apple.CoreSimulator.SimRuntime.iOS-18-5 (simulator)
    • macOS (desktop)                   • macos                                • darwin-arm64 • macOS 15.5 24F74 darwin-arm64

[✓] Network resources [856ms]
    • All expected network resources are available.

! Doctor found issues in 3 categories.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions

      pFad - Phonifier reborn

      Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

      Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


      Alternative Proxies:

      Alternative Proxy

      pFad Proxy

      pFad v3 Proxy

      pFad v4 Proxy