This package allows you to scroll/select the value directly from the dropdown with less effort and time.

Overview

Direct Select

pub package

This package allows you to scroll/select the value directly from the dropdown with less effort and time.

Inspired by Virgil Pana shot

Samples

Light

Dark

Getting started

You should ensure that you add the router as a dependency in your flutter project.

dependencies:
  direct_select: "^1.0.3"

You should then run flutter packages upgrade or update your packages in IntelliJ.

Example Project

There is an example project in the example folder. Check it out. Otherwise, keep reading to get up and running.

Usage

Sample 1

_buildItems1() { return elements1 .map((val) => MySelectionItem( title: val, )) .toList(); } List _buildItems2() { return elements2 .map((val) => MySelectionItem( title: val, )) .toList(); } List _buildItems3() { return elements3 .map((val) => MySelectionItem( title: val, )) .toList(); } List _buildItems4() { return elements4 .map((val) => MySelectionItem( title: val, )) .toList(); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text(widget.title), ), body: Padding( padding: const EdgeInsets.all(15.0), child: Center( child: Column( mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Padding( padding: const EdgeInsets.only(left: 10.0), child: Text( "To which meal?", style: TextStyle( color: Colors.grey, fontWeight: FontWeight.w500), ), ), DirectSelect( itemExtent: 35.0, selectedIndex: selectedIndex1, backgroundColor: Colors.red, child: MySelectionItem( isForList: false, title: elements1[selectedIndex1], ), onSelectedItemChanged: (index) { setState(() { selectedIndex1 = index; }); }, items: _buildItems1()), Padding( padding: const EdgeInsets.only(left: 10.0, top: 20.0), child: Text( "Search our database by name", style: TextStyle( color: Colors.grey, fontWeight: FontWeight.w500), ), ), DirectSelect( itemExtent: 35.0, selectedIndex: selectedIndex2, child: MySelectionItem( isForList: false, title: elements2[selectedIndex2], ), onSelectedItemChanged: (index) { setState(() { selectedIndex2 = index; }); }, items: _buildItems2()), Padding( padding: const EdgeInsets.only(left: 10.0, top: 20.0), child: Text( "Select your workout schedule", style: TextStyle( color: Colors.grey, fontWeight: FontWeight.w500), ), ), DirectSelect( itemExtent: 35.0, selectedIndex: selectedIndex3, child: MySelectionItem( isForList: false, title: elements3[selectedIndex3], ), onSelectedItemChanged: (index) { setState(() { selectedIndex3 = index; }); }, items: _buildItems3()), Padding( padding: const EdgeInsets.only(left: 10.0, top: 20.0), child: Text( "Select your goal", style: TextStyle( color: Colors.grey, fontWeight: FontWeight.w500), ), ), DirectSelect( itemExtent: 35.0, selectedIndex: selectedIndex4, child: MySelectionItem( isForList: false, title: elements4[selectedIndex4], ), onSelectedItemChanged: (index) { setState(() { selectedIndex4 = index; }); }, items: _buildItems4()), ]), ), ), ); } } //You can use any Widget class MySelectionItem extends StatelessWidget { final String title; final bool isForList; const MySelectionItem({Key key, this.title, this.isForList = true}) : super(key: key); @override Widget build(BuildContext context) { return SizedBox( height: 60.0, child: isForList ? Padding( child: _buildItem(context), padding: EdgeInsets.all(10.0), ) : Card( margin: EdgeInsets.symmetric(horizontal: 10.0), child: Stack( children: [ _buildItem(context), Align( alignment: Alignment.centerRight, child: Icon(Icons.arrow_drop_down), ) ], ), ), ); } _buildItem(BuildContext context) { return Container( width: MediaQuery.of(context).size.width, alignment: Alignment.center, child: Text(title), ); } } ">
import 'package:flutter/material.dart';
import 'package:direct_select/direct_select.dart';

class _MyHomePageState extends State<MyHomePage> {
  final elements1 = [
    "Breakfast",
    "Lunch",
    "2nd Snack",
    "Dinner",
    "3rd Snack",
  ];
  final elements2 = [
    "Cheese Steak",
    "Chicken",
    "Salad",
  ];

  final elements3 = [
    "7am - 10am",
    "11am - 2pm",
    "3pm - 6pm",
    "7pm-10pm",
  ];

  final elements4 = [
    "Lose fat",
    "Gain muscle",
    "Keep in weight",
  ];

  int selectedIndex1 = 0,
      selectedIndex2 = 0,
      selectedIndex3 = 0,
      selectedIndex4 = 0;

  List<Widget> _buildItems1() {
    return elements1
        .map((val) => MySelectionItem(
              title: val,
            ))
        .toList();
  }

  List<Widget> _buildItems2() {
    return elements2
        .map((val) => MySelectionItem(
              title: val,
            ))
        .toList();
  }

  List<Widget> _buildItems3() {
    return elements3
        .map((val) => MySelectionItem(
              title: val,
            ))
        .toList();
  }

  List<Widget> _buildItems4() {
    return elements4
        .map((val) => MySelectionItem(
              title: val,
            ))
        .toList();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Padding(
        padding: const EdgeInsets.all(15.0),
        child: Center(
          child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.stretch,
              children: <Widget>[
                Padding(
                  padding: const EdgeInsets.only(left: 10.0),
                  child: Text(
                    "To which meal?",
                    style: TextStyle(
                        color: Colors.grey, fontWeight: FontWeight.w500),
                  ),
                ),
                DirectSelect(
                    itemExtent: 35.0,
                    selectedIndex: selectedIndex1,
                    backgroundColor: Colors.red,
                    child: MySelectionItem(
                      isForList: false,
                      title: elements1[selectedIndex1],
                    ),
                    onSelectedItemChanged: (index) {
                      setState(() {
                        selectedIndex1 = index;
                      });
                    },
                    items: _buildItems1()),
                Padding(
                  padding: const EdgeInsets.only(left: 10.0, top: 20.0),
                  child: Text(
                    "Search our database by name",
                    style: TextStyle(
                        color: Colors.grey, fontWeight: FontWeight.w500),
                  ),
                ),
                DirectSelect(
                    itemExtent: 35.0,
                    selectedIndex: selectedIndex2,
                    child: MySelectionItem(
                      isForList: false,
                      title: elements2[selectedIndex2],
                    ),
                    onSelectedItemChanged: (index) {
                      setState(() {
                        selectedIndex2 = index;
                      });
                    },
                    items: _buildItems2()),
                Padding(
                  padding: const EdgeInsets.only(left: 10.0, top: 20.0),
                  child: Text(
                    "Select your workout schedule",
                    style: TextStyle(
                        color: Colors.grey, fontWeight: FontWeight.w500),
                  ),
                ),
                DirectSelect(
                    itemExtent: 35.0,
                    selectedIndex: selectedIndex3,
                    child: MySelectionItem(
                      isForList: false,
                      title: elements3[selectedIndex3],
                    ),
                    onSelectedItemChanged: (index) {
                      setState(() {
                        selectedIndex3 = index;
                      });
                    },
                    items: _buildItems3()),
                Padding(
                  padding: const EdgeInsets.only(left: 10.0, top: 20.0),
                  child: Text(
                    "Select your goal",
                    style: TextStyle(
                        color: Colors.grey, fontWeight: FontWeight.w500),
                  ),
                ),
                DirectSelect(
                    itemExtent: 35.0,
                    selectedIndex: selectedIndex4,
                    child: MySelectionItem(
                      isForList: false,
                      title: elements4[selectedIndex4],
                    ),
                    onSelectedItemChanged: (index) {
                      setState(() {
                        selectedIndex4 = index;
                      });
                    },
                    items: _buildItems4()),
              ]),
        ),
      ),
    );
  }
}

//You can use any Widget
class MySelectionItem extends StatelessWidget {
  final String title;
  final bool isForList;

  const MySelectionItem({Key key, this.title, this.isForList = true})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: 60.0,
      child: isForList
          ? Padding(
              child: _buildItem(context),
              padding: EdgeInsets.all(10.0),
            )
          : Card(
              margin: EdgeInsets.symmetric(horizontal: 10.0),
              child: Stack(
                children: <Widget>[
                  _buildItem(context),
                  Align(
                    alignment: Alignment.centerRight,
                    child: Icon(Icons.arrow_drop_down),
                  )
                ],
              ),
            ),
    );
  }

  _buildItem(BuildContext context) {
    return Container(
      width: MediaQuery.of(context).size.width,
      alignment: Alignment.center,
      child: Text(title),
    );
  }
}

You can follow me on twitter @diegoveloper

Comments
  • Properly use the right overlay based on engagement mode.

    Properly use the right overlay based on engagement mode.

    Works on my end, doctor -v:

    [✓] Flutter (Channel master, 1.22.0-10.0.pre.380, on Linux, locale en_US.utf8)
        • Flutter version 1.22.0-10.0.pre.380 at /home/noor/Google/Flutter
        • Framework revision ec40df9576 (2 days ago), 2020-09-25 21:27:22 -0700
        • Engine revision 3a73d073c8
        • Dart version 2.11.0 (build 2.11.0-161.0.dev)
    
    opened by noordawod 7
  • Added back button support + refactor

    Added back button support + refactor

    In order to support tapping the Back button, the implementation has to use a Dialog instead of an Overlay. The reason is that the latter transcends the Navigator and thus tapping the back button cannot be intercepted.

    I tried keeping all UX as-is, and even fixed a positioning bug when calculating the Y position of the magnified selection widget. As far as I can see, there is no UI difference.

    opened by noordawod 5
  • bug on Flutter1.5.4-hotfix.2

    bug on Flutter1.5.4-hotfix.2

    Hello, I run your Demo on Flutter1.5.4-hotfix.2 and I can't select any item. Error Message:

    Launching lib/main.dart on Android SDK built for x86 in debug mode...
    
    registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
    
    registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
    
    registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
    
    registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
    
    registerResGeneratingTask is deprecated, use registerGeneratedResFolders(FileCollection)
    
    Built build/app/outputs/apk/debug/app-debug.apk.
    
    I/CameraManagerGlobal(26534): Connecting to camera service
    
    D/EGL_emulation(26534): eglMakeCurrent: 0x9fe852a0: ver 3 0 (tinfo 0x9fe83230)
    
    I/flutter (26534): ══╡ EXCEPTION CAUGHT BY GESTURE ╞═══════════════════════════════════════════════════════════════════
    
    I/flutter (26534): The following NoSuchMethodError was thrown while handling a gesture:
    
    I/flutter (26534): The method 'reverse' was called on null.
    
    I/flutter (26534): Receiver: null
    
    I/flutter (26534): Tried calling: reverse(Instance of 'OverlayEntry')
    
    I/flutter (26534):
    
    I/flutter (26534): When the exception was thrown, this was the stack:
    
    I/flutter (26534): #0      Object.noSuchMethod  (dart:core-patch/object_patch.dart:50:5)
    
    I/flutter (26534): #1      _DirectSelectState._removeOverlay 
    
    I/flutter (26534): #2      _DirectSelectState.build.<anonymous closure> 
    
    I/flutter (26534): #3      DragGestureRecognizer.didStopTrackingLastPointer.<anonymous closure> 
    
    I/flutter (26534): #4      GestureRecognizer.invokeCallback 
    
    I/flutter (26534): #5      DragGestureRecognizer.didStopTrackingLastPointer 
    
    I/flutter (26534): #6      OneSequenceGestureRecognizer.stopTrackingPointer 
    
    I/flutter (26534): #7      OneSequenceGestureRecognizer.stopTrackingIfPointerNoLongerDown 
    
    I/flutter (26534): #8      DragGestureRecognizer.handleEvent 
    
    I/flutter (26534): #9      PointerRouter._dispatch 
    
    I/flutter (26534): #10     PointerRouter.route 
    
    I/flutter (26534): #11     _WidgetsFlutterBinding&BindingBase&GestureBinding.handleEvent 
    
    I/flutter (26534): #12     _WidgetsFlutterBinding&BindingBase&GestureBinding.dispatchEvent 
    
    I/flutter (26534): #13     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerEvent 
    
    I/flutter (26534): #14     _WidgetsFlutterBinding&BindingBase&GestureBinding._flushPointerEventQueue 
    
    I/flutter (26534): #15     _WidgetsFlutterBinding&BindingBase&GestureBinding._handlePointerDataPacket 
    
    I/flutter (26534): #19     _invoke1  (dart:ui/hooks.dart:233:10)
    
    I/flutter (26534): #20     _dispatchPointerDataPacket  (dart:ui/hooks.dart:154:5)
    
    I/flutter (26534): (elided 3 frames from package dart:async)
    
    I/flutter (26534):
    
    I/flutter (26534): Handler: onEnd
    
    I/flutter (26534): Recognizer:
    
    I/flutter (26534):   VerticalDragGestureRecognizer#f6314(debugOwner: GestureDetector, start behavior: start)
    
    I/flutter (26534): ════════════════════════════════════════════════════════════════════════════════════════════════════
    
    D/EGL_emulation(26534): eglMakeCurrent: 0x9d53bee0: ver 3 0 (tinfo 0x9b81e8f0)
    
    
    
    opened by xiongdi9456 3
  • [Security] Workflow release.yml is using vulnerable action actions/checkout

    [Security] Workflow release.yml is using vulnerable action actions/checkout

    The workflow release.yml is referencing action actions/checkout using references v1. However this reference is missing the commit a6747255bd19d7a757dbdda8c654a9f84db19839 which may contain fix to the some vulnerability. The vulnerability fix that is missing by actions version could be related to: (1) CVE fix (2) upgrade of vulnerable dependency (3) fix to secret leak and others. Please consider to update the reference to the action.

    opened by Ale0x78 1
  • Change tap behavior

    Change tap behavior

    Hi, I wanna know if have a chance to change the behavior of field. Tap and open the "modal" and wait the cliente select the correct, instead tap and hold to show options.

    opened by git-xbits 1
  • Show  only one value up and down when scrolling.

    Show only one value up and down when scrolling.

    I am using this direct select package. I want to show only one value up and down when scrolling because I have to show the 100 numbers so it takes to much place on the screen when scrolling to select value. If there is any way to do it so please let me know.

    opened by Sania-Developer 0
  • If a dialog appears when the select box is displayed, the select box cannot be closed after that.

    If a dialog appears when the select box is displayed, the select box cannot be closed after that.

    I use your package conveniently. Thank you very much.

    As the title suggests, when the DirectSelect select box (options) is displayed and a dialog appears with the showDialog method, the DirectSelect select box (options) does not disappear no matter how many times I tap the screen after that. .. (Slides occur, but the select box does not disappear.) After all, I couldn't get out without restarting the iPhone.

    mode: DirectSelectMode.tap, Physical device, iPhone SE (2nd) It has not been tested in the simulator.

    opened by wpl90 0
  • Dark mode not working

    Dark mode not working

    Dark mode is not working when running your main.dart in your example directory on my iOS simulator. Once the list is selected the background color changes to white even when dark mode is enabled.

    bug 
    opened by akaymaram 8
Owner
Diego Velásquez López
Mobile Software Architect
Diego Velásquez López
A Flutter package that provides a dropdown form field using a dropdown button inside a form field.

Dropdown form field A dropdown form field using a dropdown button inside a form field. Demo Features Can be used as regular form field. Simple to impl

Carlos Eugenio Torres 72 Jan 1, 2023
A Flutter select form field widget. It shows a list of options in a dropdown menu.

select_form_field A Flutter select field widget. It shows a list of options in a dropdown menu. This widget extend TextField and has a similar behavio

m3uzz Soluções em TI 8 Sep 14, 2022
A powerful official extension library of Tab/TabBar/TabView, which support to scroll ancestor or child Tabs when current is overscroll, and set scroll direction and cache extent.

extended_tabs Language: English | 中文简体 A powerful official extension library of Tab/TabBar/TabView, which support to scroll ancestor or child Tabs whe

FlutterCandies 185 Dec 13, 2022
Z time ago - A simple Flutter z time ago package used to change date to time ago for english, arabic and kurdish languages

This package is used to get time duration from now and given time for kurdish, a

Zakarya Muhammad 2 May 19, 2022
An Effort to gather all Flutter Create App submissions at one place from various resources.

 Flutter Create Submissions 2019 ?? An Effort to gather all Flutter Create App submissions at one place from various resources. If you would like to

Pinkesh Darji 554 Dec 17, 2022
Custom calendar dialog widget for flutter with (multi select, single select, date range) mode

some calendar Custom calendar with Multi-select & range configurable calendar New Features Added View Mode Somecalendar #15 Help Maintenance I've take

Irvan Lutfi Gunawan 69 Jan 3, 2023
Custom dropdown widget allows to add highly customizable widget in your projects with proper open and close animations and also comes with form required validation.

Custom Dropdown Custom Dropdown package lets you add customizable animated dropdown widget. Features Lots of properties to use and customize dropdown

Abdullah Chauhan 22 Dec 29, 2022
App HTTP Client is a wrapper around the HTTP library Dio to make network requests and error handling simpler, more predictable, and less verbose.

App HTTP Client App HTTP Client is a wrapper around the HTTP library Dio to make network requests and error handling simpler, more predictable, and le

Joanna May 44 Nov 1, 2022
The easiest way to use navigation, context less and useful methods.

Starlight Utils The easiest way to use navigation, context less and useful methods. Features Name Status Context Less Navigation Service ✅ Context Les

Ye Myo Aung 5 Jul 10, 2022
A Flutter package with an advanced dropdown Button which let you give different design on DropdownButton

Use decorated_dropdown button to add DropdownButton with decoration properties l

Hari Prasad Chaudhary 1 Dec 17, 2021
FLUTTER API: It's powerful navigation by gestures and taps. You can scroll from left to right or tap on the navigation icons.

scroll_navigation My other APIs Video Viewer Video Editor Helpers Features Fancy animations. Customizable colors. Works with the back button. Scrollin

Luis Felipe Murguia Ramos 14 Jun 14, 2022
A Dart package that helps to implement value based equality without needing to explicitly override == and hashCode.

Simplify Equality Comparisons Overview Being able to compare objects in Dart often involves having to override the == operator as well as hashCode. No

Felix Angelov 747 Jan 8, 2023
In this project, we will design a travel app UI with a parallax effect for a unique scroll experience. You will learn how to create your own parallax effect without using external libraries.

Travel App UI In this part, we will design a travel app UI with a parallax effect for a unique scroll experience. You will learn how to create your ow

DebugErrorX 5 Dec 5, 2022
This package adds CustomRefreshIndicator widget that allows you to create whatever indicator you want.

Custom Refresh Indicator A flutter package that allows you to easily create a custom refresh indicator widget. TLDR; ONLINE DEMO! QUICK START CustomRe

Kamil Klyta 315 Dec 16, 2022
Add beautiful and trending tab indicators directly to your default Flutter TabBar

Add beautiful and trending tab indicators directly to your default Flutter TabBar. Features ?? Supports Android, iOS, Web Can be directly added to the

Adar 51 Dec 23, 2022
ABC of Flutter widgets. Intended for super beginners at Flutter. Play with 35+ examples in DartPad directly and get familiar with various basic widgets in Flutter

Basic Widgets Examples This is aimed for complete beginners in Flutter, to get them acquainted with the various basic widgets in Flutter. Run this pro

Pooja Bhaumik 815 Jan 3, 2023
A Funtioning basic Clock UI APP with extra functionalities such as displaying thecurrent time location being used and checking time for other timezones simultaneosly.

clock_UI A new Flutter project. Getting Started This project is a starting point for a Flutter application. A few resources to get you started if this

Anjola Favour Ayomikun 0 Dec 28, 2021
Simple project that consumes the World Time APi and displays the time for the chosen location.

World Time App Simple project that consumes the World Time APi and displays the time for the chosen location. Web Api WorldTime Technologies Flutter A

Mario Vieria 1 Jan 20, 2022