0

Since updating to Flutter 3.7 i am not able to select cerain items in my CupertienoPicker.

To reproduce this issue run the following code in Windows Desktop:

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {

  int _index = 0;

  List<String> team = <String>["Olaf","Victor","Rita"] ;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: CupertinoPicker(
            itemExtent: 50,
            onSelectedItemChanged: (selectedIndex) {
              _index = selectedIndex;
            },
            children: List.generate(team.length, (index) {
              return Text(team[index]);
            }),
        ),
      ),
    );
  }
}

An issue has already filed in github.

deczaloth
  • 7,094
  • 4
  • 24
  • 59

1 Answers1

0

First thing to check is your Mouse Settings. It is known that the issue might appear if you have set "Multiple lines at a time". To check this go to Settings -> Devices -> Mouse and set "Choose how many lines to scroll each time" to 1.

If this does not fix your issue read below.


The issue seems in deed a bug in the latest Flutter 3.7.

As a work around i had to add a listener to the CupertinoPicker's scrollerController and perform the jumps programatically as follows

var c = FixedExtentScrollController();
c.addListener(() {
  if (previousIndex != c.selectedItem) {
    isScrollDown = previousIndex<c.selectedItem;
    isScrollUp = previousIndex>c.selectedItem;

    var previousIndexTemp = previousIndex;
    previousIndex = c.selectedItem;

    if (isScrollUp) {
      c.jumpToItem(previousIndexTemp - 1);
    } else if (isScrollDown) {
      c.jumpToItem(previousIndexTemp + 1);
    }
  }
});

...

CupertinoPicker(
  scrollController: c,
...

Here is a modified version of the code above that applies the mentioned work around:

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

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

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

class _MyHomePageState extends State<MyHomePage> {

  int _index = 0;
  int previousIndex = 0;
  bool isScrollUp = false;
  bool isScrollDown = true;

  List<String> team = <String>["Olaf","Victor","Rita"] ;

  FixedExtentScrollController c = FixedExtentScrollController();

  @override
  void initState() {
    c.addListener(_manageScroll);

    super.initState();
  }

  void _manageScroll () {
    if (previousIndex != c.selectedItem) {
      isScrollDown = previousIndex<c.selectedItem;
      isScrollUp = previousIndex>c.selectedItem;

      var previousIndexTemp = previousIndex;
      previousIndex = c.selectedItem;

      if (isScrollUp) {
        c.jumpToItem(previousIndexTemp - 1);
      } else if (isScrollDown) {
        c.jumpToItem(previousIndexTemp + 1);
      }
    }
  }

  @override
  void dispose() {
    c.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: CupertinoPicker(
          scrollController: c,
            itemExtent: 50,
            onSelectedItemChanged: (selectedIndex) {
              _index = selectedIndex;
            },
            children: List.generate(team.length, (index) {
              return Text(team[index]);
            }),
        ),
      ),
    );
  }
}
deczaloth
  • 7,094
  • 4
  • 24
  • 59