diff --git a/CHANGELOG.md b/CHANGELOG.md index 8263042..1f74e02 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,8 @@ +## [1.0.8] - ???? + +* Allow use of Long Press to open select box +* Now DirectSelect overlay takes same size as underlying child + ## [1.0.7] - 2020.12.02 * Remove redundant dependencies diff --git a/example/lib/main.dart b/example/lib/main.dart index b43574f..70937f2 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -44,14 +44,14 @@ class _MyHomePageState extends State { "Pork grilled", "Vegetables as is", "Cheese as is", - "Bread tasty" + "Bread tasty", ]; List _portionSize = [ "Small portion", "Medium portion", "Large portion", - "Huge portion" + "Huge portion", ]; List _numbers = ["1.0", "2.0", "3.0", "4.0", "5.0", "6.0", "7.0"]; @@ -85,29 +85,37 @@ class _MyHomePageState extends State { final appBar = PreferredSize( child: Container( decoration: BoxDecoration( - color: Color.fromRGBO(246, 247, 249, 1), - border: BorderDirectional( - bottom: BorderSide(width: 1, color: Colors.black12))), + color: Color.fromRGBO(246, 247, 249, 1), + border: BorderDirectional( + bottom: BorderSide(width: 1, color: Colors.black12), + ), + ), child: Padding( padding: EdgeInsets.only(left: 16, bottom: 24), - child: Column( - verticalDirection: VerticalDirection.up, - children: [ - Container( - alignment: AlignmentDirectional.centerStart, - child: Text("Add Food", - style: TextStyle( - fontSize: 26, - color: Colors.black, - fontWeight: FontWeight.bold))), - Container( - alignment: AlignmentDirectional.centerStart, - child: Text("Journal", - style: TextStyle( - fontSize: 12, - color: Colors.black38, - fontWeight: FontWeight.bold))) - ])), + child: Column(verticalDirection: VerticalDirection.up, children: [ + Container( + alignment: AlignmentDirectional.centerStart, + child: Text( + "Add Food", + style: TextStyle( + fontSize: 26, + color: Colors.black, + fontWeight: FontWeight.bold, + ), + ), + ), + Container( + alignment: AlignmentDirectional.centerStart, + child: Text( + "Journal", + style: TextStyle( + fontSize: 12, + color: Colors.black38, + fontWeight: FontWeight.bold, + ), + ), + ) + ])), ), preferredSize: Size.fromHeight(90)); @@ -129,9 +137,10 @@ class _MyHomePageState extends State { margin: EdgeInsets.only(left: 4), child: Column( children: [ - Text(_foodVariants[selectedFoodVariants], - style: TextStyle( - fontSize: 26, fontWeight: FontWeight.bold)) + Text( + _foodVariants[selectedFoodVariants], + style: TextStyle(fontSize: 26, fontWeight: FontWeight.bold), + ) ], )), Container( @@ -139,11 +148,7 @@ class _MyHomePageState extends State { alignment: AlignmentDirectional.centerStart, margin: EdgeInsets.only(left: 4), child: Column( - children: [ - Text(_numbers[selectedPortionCounts] + - " " + - _portionSize[selectedPortionSize]) - ], + children: [Text(_numbers[selectedPortionCounts] + " " + _portionSize[selectedPortionSize])], )), SizedBox(height: 5.0), _getFoodContainsRow(), @@ -154,8 +159,7 @@ class _MyHomePageState extends State { children: [ MealSelector(data: _meals, label: "To which meal?"), SizedBox(height: 20.0), - MealSelector( - data: _food, label: "Search our database by name"), + MealSelector(data: _food, label: "Search our database by name"), Padding( padding: EdgeInsets.fromLTRB(0, 8, 0, 0), child: Container( @@ -168,17 +172,14 @@ class _MyHomePageState extends State { child: Padding( child: DirectSelectList( values: _foodVariants, + useLongPressGesture: true, onUserTappedListener: () { _showScaffold(); }, - defaultItemIndex: - selectedFoodVariants, - itemBuilder: (String value) => - getDropDownMenuItem(value), - focusedItemDecoration: - _getDslDecoration(), - onItemSelectedListener: - (item, index, context) { + defaultItemIndex: selectedFoodVariants, + itemBuilder: (String value) => getDropDownMenuItem(value), + focusedItemDecoration: _getDslDecoration(), + onItemSelectedListener: (item, index, context) { setState(() { selectedFoodVariants = index; }); @@ -215,14 +216,10 @@ class _MyHomePageState extends State { _showScaffold(); }, values: _numbers, - defaultItemIndex: - selectedPortionCounts, - itemBuilder: (String value) => - getDropDownMenuItem(value), - focusedItemDecoration: - _getDslDecoration(), - onItemSelectedListener: - (item, index, context) { + defaultItemIndex: selectedPortionCounts, + itemBuilder: (String value) => getDropDownMenuItem(value), + focusedItemDecoration: _getDslDecoration(), + onItemSelectedListener: (item, index, context) { setState(() { selectedPortionCounts = index; }); @@ -243,14 +240,10 @@ class _MyHomePageState extends State { child: Padding( child: DirectSelectList( values: _portionSize, - defaultItemIndex: - selectedPortionSize, - itemBuilder: (String value) => - getDropDownMenuItem(value), - focusedItemDecoration: - _getDslDecoration(), - onItemSelectedListener: - (item, index, context) { + defaultItemIndex: selectedPortionSize, + itemBuilder: (String value) => getDropDownMenuItem(value), + focusedItemDecoration: _getDslDecoration(), + onItemSelectedListener: (item, index, context) { setState(() { selectedPortionSize = index; }); @@ -267,8 +260,10 @@ class _MyHomePageState extends State { Row(children: [ Expanded( child: RaisedButton( - child: const Text('ADD TO JOURNAL', - style: TextStyle(color: Colors.blueAccent)), + child: const Text( + 'ADD TO JOURNAL', + style: TextStyle(color: Colors.blueAccent), + ), onPressed: () {}, )) ]), @@ -322,9 +317,10 @@ class MealSelector extends StatelessWidget { return Column( children: [ Container( - alignment: AlignmentDirectional.centerStart, - margin: EdgeInsets.only(left: 4), - child: Text(label)), + alignment: AlignmentDirectional.centerStart, + margin: EdgeInsets.only(left: 4), + child: Text(label), + ), Padding( padding: buttonPadding, child: Container( @@ -338,8 +334,7 @@ class MealSelector extends StatelessWidget { child: DirectSelectList( values: data, defaultItemIndex: 0, - itemBuilder: (String value) => - getDropDownMenuItem(value), + itemBuilder: (String value) => getDropDownMenuItem(value), focusedItemDecoration: _getDslDecoration(), ), padding: EdgeInsets.only(left: 12))), @@ -403,14 +398,17 @@ Widget _getFoodContainsRow() { children: [ Expanded( child: Container( - child: Center(child: Text("226")), - height: cardSize, - margin: EdgeInsets.only(right: 3), - decoration: BoxDecoration( - color: cardColor, - borderRadius: BorderRadius.only( - topLeft: const Radius.circular(10.0), - bottomLeft: const Radius.circular(10.0)))), + child: Center(child: Text("226")), + height: cardSize, + margin: EdgeInsets.only(right: 3), + decoration: BoxDecoration( + color: cardColor, + borderRadius: BorderRadius.only( + topLeft: const Radius.circular(10.0), + bottomLeft: const Radius.circular(10.0), + ), + ), + ), ), Expanded( child: Container( @@ -428,13 +426,16 @@ Widget _getFoodContainsRow() { ), Expanded( child: Container( - child: Center(child: Text("4.5")), - height: cardSize, - decoration: BoxDecoration( - color: cardColor, - borderRadius: BorderRadius.only( - topRight: const Radius.circular(10.0), - bottomRight: const Radius.circular(10.0)))), + child: Center(child: Text("4.5")), + height: cardSize, + decoration: BoxDecoration( + color: cardColor, + borderRadius: BorderRadius.only( + topRight: const Radius.circular(10.0), + bottomRight: const Radius.circular(10.0), + ), + ), + ), ), ], ), diff --git a/lib/direct_select_container.dart b/lib/direct_select_container.dart index 41f2e26..b478e38 100644 --- a/lib/direct_select_container.dart +++ b/lib/direct_select_container.dart @@ -1,11 +1,12 @@ import 'dart:async'; -import 'package:direct_select_flutter/direct_select_list.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:rect_getter/rect_getter.dart'; +import './direct_select_list.dart'; + /// Root widget for direct select. /// This widget displays lists of direct selects. /// Usage Example @@ -86,15 +87,10 @@ class DirectSelectContainer extends StatefulWidget { } static DirectSelectGestureEventListeners of(BuildContext context) { - if (context.dependOnInheritedWidgetOfExactType< - _InheritedContainerListeners>() == - null) { - throw Exception( - "A DirectSelectList must inherit a DirectSelectContainer!"); + if (context.dependOnInheritedWidgetOfExactType<_InheritedContainerListeners>() == null) { + throw Exception("A DirectSelectList must inherit a DirectSelectContainer!"); } - return context - .dependOnInheritedWidgetOfExactType<_InheritedContainerListeners>() - .listeners; + return context.dependOnInheritedWidgetOfExactType<_InheritedContainerListeners>().listeners; } } @@ -104,8 +100,7 @@ class DirectSelectContainerState extends State bool isOverlayVisible = false; ScrollController _scrollController; - DirectSelectList _currentList = - DirectSelectList(itemBuilder: (val) => null, values: []); + DirectSelectList _currentList = DirectSelectList(itemBuilder: (val) => null, values: []); double _currentScrollLocation = 0; double _adjustedTopOffset = 0.0; @@ -132,19 +127,17 @@ class DirectSelectContainerState extends State @override Widget build(BuildContext context) { double topOffset = 0.0; - RenderObject object = context.findRenderObject(); - if (object?.parentData is ContainerBoxParentData) { - topOffset = (object.parentData as ContainerBoxParentData).offset.dy; - } + RenderBox object = context.findRenderObject() as RenderBox; + if (object != null) { + topOffset = object.localToGlobal(Offset.zero).dy; + } listPadding = MediaQuery.of(context).size.height; - _adjustedTopOffset = _currentScrollLocation - topOffset; + _scrollController = ScrollController( - initialScrollOffset: listPadding - - _currentScrollLocation + - topOffset + - _currentList.getSelectedItemIndex() * _currentList.itemHeight()); + initialScrollOffset: + listPadding - _currentScrollLocation + topOffset + _currentList.getSelectedItemIndex() * _currentList.itemHeight()); return Stack( children: [ @@ -152,22 +145,23 @@ class DirectSelectContainerState extends State listeners: this, child: widget.child, ), - Visibility( - visible: isOverlayVisible, - child: FadeTransition( - opacity: fadeAnimationController - .drive(CurveTween(curve: Curves.easeOut)), - child: Column( - children: [ - Expanded( - child: Stack( - children: [ - _getListWidget(), - _getSelectionOverlayWidget(), - ], + Positioned.fill( + child: Visibility( + visible: isOverlayVisible, + child: FadeTransition( + opacity: fadeAnimationController.drive(CurveTween(curve: Curves.easeOut)), + child: Column( + children: [ + Expanded( + child: Stack( + children: [ + _getListWidget(), + _getSelectionOverlayWidget(), + ], + ), ), - ), - ], + ], + ), ), ), ) @@ -179,8 +173,7 @@ class DirectSelectContainerState extends State var paddingLeft = 0.0; if (_currentList.items.isNotEmpty) { - Rect rect = RectGetter.getRectFromKey( - _currentList.paddingItemController.paddingGlobalKey); + Rect rect = RectGetter.getRectFromKey(_currentList.paddingItemController.paddingGlobalKey); if (rect != null) { paddingLeft = rect.left; } @@ -189,8 +182,7 @@ class DirectSelectContainerState extends State Decoration dslContainerDecoration; if (widget.decoration == null) { final theme = Theme.of(context); - dslContainerDecoration = - BoxDecoration(color: theme.scaffoldBackgroundColor); + dslContainerDecoration = BoxDecoration(color: theme.scaffoldBackgroundColor); } else { dslContainerDecoration = widget.decoration; } @@ -218,29 +210,25 @@ class DirectSelectContainerState extends State Widget _getSelectionOverlayWidget() { return Positioned( - top: _adjustedTopOffset, - left: 0, - right: 0, - height: _currentList.itemHeight(), - child: Container( - height: _currentList.itemHeight(), - decoration: _currentList.focusedItemDecoration != null - ? _currentList.focusedItemDecoration - : BoxDecoration())); + top: _adjustedTopOffset, + left: 0, + right: 0, + height: _currentList.itemHeight(), + child: Container( + height: _currentList.itemHeight(), + decoration: _currentList.focusedItemDecoration != null ? _currentList.focusedItemDecoration : BoxDecoration()), + ); } void performListDrag(double dragDy) { try { if (_scrollController != null && _scrollController.position != null) { final currentScrollOffset = _scrollController.offset; - double allowedOffset = _allowedDragDistance( - currentScrollOffset + _adjustedTopOffset, - dragDy * widget.dragSpeedMultiplier); + double allowedOffset = _allowedDragDistance(currentScrollOffset + _adjustedTopOffset, dragDy * widget.dragSpeedMultiplier); if (allowedOffset != 0.0) { _scrollController.jumpTo(currentScrollOffset + allowedOffset); - final scrollPixels = - _scrollController.offset - listPadding + _adjustedTopOffset; + final scrollPixels = _scrollController.offset - listPadding + _adjustedTopOffset; final selectedItemIndex = _getCurrentListElementIndex(scrollPixels); lastSelectedItem = selectedItemIndex; @@ -254,9 +242,7 @@ class DirectSelectContainerState extends State double _allowedDragDistance(double currentScrollOffset, double position) { double newPosition = currentScrollOffset + position; - double endOfListPosition = - (_currentList.items.length - 1) * _currentList.itemHeight() + - listPadding; + double endOfListPosition = (_currentList.items.length - 1) * _currentList.itemHeight() + listPadding; if (newPosition < listPadding) { return listPadding - currentScrollOffset; } else if (newPosition > endOfListPosition) { @@ -268,13 +254,11 @@ class DirectSelectContainerState extends State void _performScaleTransformation(double scrollPixels, int selectedItemIndex) { final neighbourDistance = _getNeighbourListElementDistance(scrollPixels); - int neighbourIncrementDirection = - neighbourScrollDirection(neighbourDistance); + int neighbourIncrementDirection = neighbourScrollDirection(neighbourDistance); int neighbourIndex = lastSelectedItem + neighbourIncrementDirection; - double neighbourDistanceToCurrentItem = - _getNeighbourListElementDistanceToCurrentItem(neighbourDistance); + double neighbourDistanceToCurrentItem = _getNeighbourListElementDistanceToCurrentItem(neighbourDistance); if (neighbourIndex < 0 || neighbourIndex > _currentList.items.length - 1) { //incorrect neighbour index quit @@ -283,14 +267,11 @@ class DirectSelectContainerState extends State _currentList.items[selectedItemIndex].updateOpacity(1.0); _currentList.items[neighbourIndex].updateOpacity(0.5); - _currentList.items[selectedItemIndex] - .updateScale(_calculateNewScale(neighbourDistanceToCurrentItem)); - _currentList.items[neighbourIndex] - .updateScale(_calculateNewScale(neighbourDistance.abs())); + _currentList.items[selectedItemIndex].updateScale(_calculateNewScale(neighbourDistanceToCurrentItem)); + _currentList.items[neighbourIndex].updateScale(_calculateNewScale(neighbourDistance.abs())); } - double _calculateNewScale(double distance) => - 1.0 + distance / _currentList.items[lastSelectedItem].scaleFactor; + double _calculateNewScale(double distance) => 1.0 + distance / _currentList.items[lastSelectedItem].scaleFactor; int neighbourScrollDirection(double neighbourDistance) { int neighbourScrollDirection = 0; @@ -302,12 +283,10 @@ class DirectSelectContainerState extends State return neighbourScrollDirection; } - double _getNeighbourListElementDistanceToCurrentItem( - double neighbourDistance) { + double _getNeighbourListElementDistanceToCurrentItem(double neighbourDistance) { double neighbourDistanceToCurrentItem = (1 - neighbourDistance.abs()); - if (neighbourDistanceToCurrentItem > 1 || - neighbourDistanceToCurrentItem < 0) { + if (neighbourDistanceToCurrentItem > 1 || neighbourDistanceToCurrentItem < 0) { neighbourDistanceToCurrentItem = 1.0; } return neighbourDistanceToCurrentItem; @@ -327,20 +306,16 @@ class DirectSelectContainerState extends State } double _getNeighbourListElementDistance(double scrollPixels) { - double selectedElementDeviation = - (scrollPixels / _currentList.itemHeight()); + double selectedElementDeviation = (scrollPixels / _currentList.itemHeight()); int selectedElement = _getCurrentListElementIndex(scrollPixels); return selectedElementDeviation - selectedElement; } - Future toggleListOverlayVisibility( - DirectSelectList visibleList, double location) async { + Future toggleListOverlayVisibility(DirectSelectList visibleList, double location) async { if (isOverlayVisible) { try { await _scrollController.animateTo( - listPadding - - _adjustedTopOffset + - lastSelectedItem * _currentList.itemHeight(), + listPadding - _adjustedTopOffset + lastSelectedItem * _currentList.itemHeight(), duration: scrollToListElementAnimationDuration, curve: Curves.ease, ); @@ -379,10 +354,9 @@ class DirectSelectContainerState extends State } class DirectSelectGestureEventListeners { - toggleListOverlayVisibility(DirectSelectList list, double location) => - throw 'Not implemented.'; + Future toggleListOverlayVisibility(DirectSelectList list, double location) => throw 'Not implemented.'; - performListDrag(double dragDy) => throw 'Not implemented'; + void performListDrag(double dragDy) => throw 'Not implemented'; } /// Allows Direct Select List implementations to @@ -396,6 +370,5 @@ class _InheritedContainerListeners extends InheritedWidget { }) : super(key: key, child: child); @override - bool updateShouldNotify(_InheritedContainerListeners old) => - old.listeners != listeners; + bool updateShouldNotify(_InheritedContainerListeners old) => old.listeners != listeners; } diff --git a/lib/direct_select_list.dart b/lib/direct_select_list.dart index 91d9920..49b4b64 100644 --- a/lib/direct_select_list.dart +++ b/lib/direct_select_list.dart @@ -1,17 +1,17 @@ -import 'package:direct_select_flutter/direct_select_container.dart'; -import 'package:direct_select_flutter/direct_select_item.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:rect_getter/rect_getter.dart'; +import './direct_select_container.dart'; +import './direct_select_item.dart'; + typedef DirectSelectItemsBuilder = DirectSelectItem Function(T value); class PaddingItemController { GlobalKey paddingGlobalKey = RectGetter.createGlobalKey(); } -typedef ItemSelected = Future Function( - DirectSelectList owner, double location); +typedef ItemSelected = Future Function(DirectSelectList owner, double location); /// Widget that contains items and responds to user's interaction /// Usage Example @@ -35,8 +35,10 @@ class DirectSelectList extends StatefulWidget { final ValueNotifier selectedItem; ///Function to execute when item selected - final Function(T value, int selectedIndex, BuildContext context) - onItemSelectedListener; + final Function(T value, int selectedIndex, BuildContext context) onItemSelectedListener; + + /// If true then LongPress is set to trigger the Drag instead of Tap (better in cases when you use DirectSelect inside of some Scrollable, ex. bottom sheet) + final bool useLongPressGesture; ///Callback for action when user just tapped instead of hold and scroll final VoidCallback onUserTappedListener; @@ -52,6 +54,7 @@ class DirectSelectList extends StatefulWidget { this.focusedItemDecoration, this.defaultItemIndex = 0, this.onUserTappedListener, + this.useLongPressGesture = false, }) : items = values.map((val) => itemBuilder(val)).toList(), selectedItem = ValueNotifier(defaultItemIndex), assert(defaultItemIndex + 1 <= values.length + 1), @@ -90,8 +93,7 @@ class DirectSelectList extends StatefulWidget { } class DirectSelectState extends State> { - final GlobalKey animatedStateKey = - GlobalKey(); + final GlobalKey animatedStateKey = GlobalKey(); Future Function(DirectSelectList, double) onTapEventListener; void Function(double) onDragEventListener; @@ -100,6 +102,7 @@ class DirectSelectState extends State> { int lastSelectedItem; bool _isShowUpAnimationRunning = false; + double longPressPosition; Map selectedItemWidgets = Map(); @@ -112,8 +115,7 @@ class DirectSelectState extends State> { @override void didUpdateWidget(DirectSelectList oldWidget) { - widget.paddingItemController.paddingGlobalKey = - oldWidget.paddingItemController.paddingGlobalKey; + widget.paddingItemController.paddingGlobalKey = oldWidget.paddingItemController.paddingGlobalKey; _updateSelectItemWidget(); super.didUpdateWidget(widget); } @@ -135,8 +137,7 @@ class DirectSelectState extends State> { void didChangeDependencies() { super.didChangeDependencies(); final dsListener = DirectSelectContainer.of(context); - assert(dsListener != null, - "A DirectSelectList must inherit a DirectSelectContainer!"); + assert(dsListener != null, "A DirectSelectList must inherit a DirectSelectContainer!"); this.onTapEventListener = dsListener.toggleListOverlayVisibility; this.onDragEventListener = dsListener.performListDrag; @@ -146,56 +147,18 @@ class DirectSelectState extends State> { Widget build(BuildContext context) { widget.selectedItem.addListener(() { if (widget.onItemSelectedListener != null) { - widget.onItemSelectedListener( - widget.items[widget.selectedItem.value].value, - widget.selectedItem.value, - this.context); + widget.onItemSelectedListener(widget.items[widget.selectedItem.value].value, widget.selectedItem.value, this.context); } }); - bool transitionEnded = false; - return ValueListenableBuilder( valueListenable: widget.selectedItem, builder: (context, value, child) { final selectedItem = selectedItemWidgets[value]; - return GestureDetector( - child: selectedItem, - onTap: () { - if (widget.onUserTappedListener != null) { - widget.onUserTappedListener(); - } - }, - onTapDown: (tapDownDetails) async { - if (!isOverlayVisible) { - transitionEnded = false; - _isShowUpAnimationRunning = true; - await animatedStateKey.currentState - .runScaleTransition(reverse: false); - if (!transitionEnded) { - await _showListOverlay(_getItemTopPosition(context)); - _isShowUpAnimationRunning = false; - lastSelectedItem = value; - } - } - }, - onTapUp: (tapUpDetails) async { - await _hideListOverlay(_getItemTopPosition(context)); - animatedStateKey.currentState.runScaleTransition(reverse: true); - }, - onVerticalDragEnd: (dragDetails) async { - transitionEnded = true; - _dragEnd(); - }, - onHorizontalDragEnd: (horizontalDetails) async { - transitionEnded = true; - _dragEnd(); - }, - onVerticalDragUpdate: (dragInfo) { - if (!_isShowUpAnimationRunning) { - _showListOverlay(dragInfo.primaryDelta); - } - }); + if (widget.useLongPressGesture) { + return _buildGestureDetectorForLongPress(context, value, selectedItem); + } + return _buildGestureDetectorForDrag(context, value, selectedItem); }); } @@ -229,4 +192,79 @@ class DirectSelectState extends State> { onDragEventListener(dy); } } + + _buildGestureDetectorForDrag(BuildContext context, int value, Widget child) { + var transitionEnded = false; + + return GestureDetector( + child: child, + onTap: widget.onUserTappedListener, + onTapDown: (tapDownDetails) async { + if (!isOverlayVisible) { + transitionEnded = false; + _isShowUpAnimationRunning = true; + await animatedStateKey.currentState.runScaleTransition(reverse: false); + if (!transitionEnded) { + await _showListOverlay(_getItemTopPosition(context)); + _isShowUpAnimationRunning = false; + lastSelectedItem = value; + } + } + }, + onTapUp: (tapUpDetails) async { + await _hideListOverlay(_getItemTopPosition(context)); + animatedStateKey.currentState.runScaleTransition(reverse: true); + }, + onVerticalDragEnd: (dragDetails) async { + transitionEnded = true; + _dragEnd(); + }, + onHorizontalDragEnd: (horizontalDetails) async { + transitionEnded = true; + _dragEnd(); + }, + onVerticalDragUpdate: (dragInfo) { + if (!_isShowUpAnimationRunning) { + _showListOverlay(dragInfo.primaryDelta); + } + }); + } + + _buildGestureDetectorForLongPress(BuildContext context, int value, Widget selectedItem) { + var transitionEnded = false; + return GestureDetector( + child: selectedItem, + onTap: widget.onUserTappedListener, + onLongPressStart: (longPressDetails) async { + if (!isOverlayVisible) { + longPressPosition = longPressDetails.localPosition.dy; + transitionEnded = false; + _isShowUpAnimationRunning = true; + await animatedStateKey.currentState.runScaleTransition(reverse: false); + if (!transitionEnded) { + await _showListOverlay(_getItemTopPosition(context)); + _isShowUpAnimationRunning = false; + lastSelectedItem = value; + } + } + }, + onLongPressEnd: (longPressEnd) async { + await _hideListOverlay(_getItemTopPosition(context)); + animatedStateKey.currentState.runScaleTransition(reverse: true); + transitionEnded = true; + _dragEnd(); + }, + onLongPressMoveUpdate: (longPressDragDetails) async { + if (!_isShowUpAnimationRunning) { + final delta = longPressPosition - longPressDragDetails.localOffsetFromOrigin.dy; + _showListOverlay(delta); + longPressPosition = longPressDragDetails.localOffsetFromOrigin.dy; + } + }, + onLongPressUp: () { + transitionEnded = true; + _dragEnd(); + }, + ); + } } diff --git a/pubspec.yaml b/pubspec.yaml index d71ceb0..439924c 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: direct_select_flutter description: Direct Select Widget Implementation inspired by https://dribbble.com/shots/3876250-DirectSelect-Dropdown-ux homepage: https://github.com/LanarsInc/direct-select-flutter -version: 1.0.7 +version: 1.0.8 environment: sdk: ">=2.1.0 <3.0.0"