From 9cb99d082caad6bb856400fdd3d4b79b6429e0bf Mon Sep 17 00:00:00 2001 From: Pierre Moati Date: Fri, 23 Dec 2022 02:43:58 +0100 Subject: [PATCH 1/2] added class with generic --- example/lib/main.dart | 108 +++++++++++++++------------- example/lib/other_screen.dart | 12 ++-- lib/cool_dropdown.dart | 132 ++++++++++++++++------------------ lib/drop_down_body.dart | 78 ++++++++++---------- lib/drop_down_params.dart | 15 ++++ 5 files changed, 183 insertions(+), 162 deletions(-) create mode 100644 lib/drop_down_params.dart diff --git a/example/lib/main.dart b/example/lib/main.dart index f145a9d..af514ee 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,18 +1,24 @@ -import 'package:flutter/material.dart'; import 'package:cool_dropdown/cool_dropdown.dart'; +import 'package:cool_dropdown/drop_down_params.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; void main() { runApp(MyApp()); } +class FruitQuantity { + final String name; + final int quantity; + + FruitQuantity({this.name, this.quantity}); +} + class MyApp extends StatefulWidget { @override _MyAppState createState() => _MyAppState(); } -List dropdownItemList = []; - List pokemons = [ 'pikachu', 'charmander', @@ -23,60 +29,60 @@ List pokemons = [ 'psyduck', 'meowth' ]; -List fruits = [ - 'apple', - 'banana', - 'grapes', - 'lemon', - 'melon', - 'orange', - 'pineapple', - 'strawberry', - 'watermelon', + +List> dropdownItemList = []; + +List fruits = [ + FruitQuantity(name: 'apple', quantity: 12), + FruitQuantity(name: 'banana', quantity: 4), + FruitQuantity(name: 'grapes', quantity: 2), + FruitQuantity(name: 'lemon', quantity: 8), + FruitQuantity(name: 'melon', quantity: 2), + FruitQuantity(name: 'orange', quantity: 7), + FruitQuantity(name: 'pineapple', quantity: 1), + FruitQuantity(name: 'strawberry', quantity: 4), + FruitQuantity(name: 'watermelon', quantity: 2), ]; class _MyAppState extends State { - List pokemonsMap = []; + List> pokemonsDropdownList = []; @override void initState() { - for (var i = 0; i < pokemons.length; i++) { - pokemonsMap.add({ - 'label': '${pokemons[i]}', - 'value': '${pokemons[i]}', - 'icon': Container( - height: 25, - width: 25, - child: SvgPicture.asset( - 'assets/${pokemons[i]}.svg', - ), - ), - }); - } - for (var i = 0; i < fruits.length; i++) { - dropdownItemList.add( - { - 'label': fruits[i] == 'melon' ? 'melon sugar high' : '${fruits[i]}', - // 'label': '${fruits[i]}', - 'value': '${fruits[i]}', - 'icon': Container( - key: UniqueKey(), - height: 20, - width: 20, + pokemonsDropdownList = pokemons.map((pokemon) => DropDownParams( + label: pokemon, + value: pokemon, + icon: Container( + height: 25, + width: 25, child: SvgPicture.asset( - 'assets/${fruits[i]}.svg', + 'assets/$pokemon.svg', ), ), - 'selectedIcon': Container( - key: UniqueKey(), - width: 20, - height: 20, - child: SvgPicture.asset( - 'assets/${fruits[i]}.svg', - color: Color(0xFF6FCC76), - ), + )); + + for (var i = 0; i < fruits.length; i++) { + dropdownItemList.add(DropDownParams( + label: fruits[i].name == 'melon' ? 'melon sugar high' : fruits[i].name, + // 'label': '${fruits[i]}', + value: fruits[i], + icon: Container( + key: UniqueKey(), + height: 20, + width: 20, + child: SvgPicture.asset( + 'assets/${fruits[i]}.svg', ), - }, - ); + ), + selectedIcon: Container( + key: UniqueKey(), + width: 20, + height: 20, + child: SvgPicture.asset( + 'assets/${fruits[i]}.svg', + color: Color(0xFF6FCC76), + ), + ), + )); } super.initState(); } @@ -96,7 +102,7 @@ class _MyAppState extends State { height: 100, ), Center( - child: CoolDropdown( + child: CoolDropdown( dropdownList: dropdownItemList, onChange: (selectedItem) { print(selectedItem); @@ -147,8 +153,8 @@ class _MyAppState extends State { height: 200, ), Center( - child: CoolDropdown( - dropdownList: pokemonsMap, + child: CoolDropdown( + dropdownList: pokemonsDropdownList, dropdownItemPadding: EdgeInsets.zero, onChange: (dropdownItem) {}, resultHeight: 50, diff --git a/example/lib/other_screen.dart b/example/lib/other_screen.dart index 18e5935..a3a95a6 100644 --- a/example/lib/other_screen.dart +++ b/example/lib/other_screen.dart @@ -1,5 +1,6 @@ -import 'package:flutter/material.dart'; import 'package:cool_dropdown/cool_dropdown.dart'; +import 'package:cool_dropdown/drop_down_params.dart'; +import 'package:flutter/material.dart'; class OtherScreen extends StatefulWidget { const OtherScreen({Key key}) : super(key: key); @@ -14,9 +15,12 @@ class _OtherScreenState extends State { return Scaffold( body: Center( child: Container( - child: CoolDropdown(dropdownList: [ - {'label': 'apple', 'value': 'apple'} - ], onChange: (_) {}), + child: CoolDropdown(dropdownList: [ + DropDownParams( + label: 'Apple', + value: 'apple', + ), + ], onChange: (_) => print(_.value)), ), ), ); diff --git a/lib/cool_dropdown.dart b/lib/cool_dropdown.dart index f8e5b2e..411ca86 100644 --- a/lib/cool_dropdown.dart +++ b/lib/cool_dropdown.dart @@ -1,68 +1,69 @@ library cool_dropdown; -import 'package:flutter/material.dart'; +import 'package:cool_dropdown/drop_down_body.dart'; +import 'package:cool_dropdown/drop_down_params.dart'; import 'package:cool_dropdown/utils/animation_util.dart'; import 'package:cool_dropdown/utils/extension_util.dart'; -import 'package:cool_dropdown/drop_down_body.dart'; +import 'package:flutter/material.dart'; -class CoolDropdown extends StatefulWidget { - List dropdownList; - Function onChange; - Function? onOpen; - String placeholder; - late Map defaultValue; - bool isTriangle; - bool isAnimation; - bool isResultIconLabel; - bool isResultLabel; - bool isDropdownLabel; // late - bool resultIconRotation; - late Widget resultIcon; - double resultIconRotationValue; +class CoolDropdown extends StatefulWidget { + final List> dropdownList; + final void Function(DropDownParams) onChange; + final void Function(bool)? onOpen; + final String placeholder; + final DropDownParams? defaultValue; + final bool isTriangle; + final bool isAnimation; + final bool isResultIconLabel; + final bool isResultLabel; + final bool isDropdownLabel; // late + final bool resultIconRotation; + late final Widget resultIcon; + final double resultIconRotationValue; // size - double resultWidth; - double resultHeight; - double? dropdownWidth; // late - double dropdownHeight; // late - double dropdownItemHeight; - double triangleWidth; - double triangleHeight; - double iconSize; + final double resultWidth; + final double resultHeight; + final double? dropdownWidth; // late + final double dropdownHeight; // late + final double dropdownItemHeight; + final double triangleWidth; + final double triangleHeight; + final double iconSize; // align - Alignment resultAlign; - String dropdownAlign; // late - Alignment dropdownItemAlign; - String triangleAlign; - double triangleLeft; - bool dropdownItemReverse; - bool resultReverse; - MainAxisAlignment resultMainAxis; - MainAxisAlignment dropdownItemMainAxis; + final Alignment resultAlign; + final String dropdownAlign; // late + final Alignment dropdownItemAlign; + final String triangleAlign; + final double triangleLeft; + final bool dropdownItemReverse; + final bool resultReverse; + final MainAxisAlignment resultMainAxis; + final MainAxisAlignment dropdownItemMainAxis; // padding - EdgeInsets resultPadding; - EdgeInsets dropdownItemPadding; - EdgeInsets dropdownPadding; // late - EdgeInsets selectedItemPadding; + final EdgeInsets resultPadding; + final EdgeInsets dropdownItemPadding; + final EdgeInsets dropdownPadding; // late + final EdgeInsets selectedItemPadding; // style - late BoxDecoration resultBD; - late BoxDecoration dropdownBD; // late - late BoxDecoration selectedItemBD; - late TextStyle selectedItemTS; - late TextStyle unselectedItemTS; - late TextStyle resultTS; - late TextStyle placeholderTS; + late final BoxDecoration resultBD; + late final BoxDecoration dropdownBD; // late + late final BoxDecoration selectedItemBD; + late final TextStyle selectedItemTS; + late final TextStyle unselectedItemTS; + late final TextStyle resultTS; + late final TextStyle placeholderTS; // gap - double gap; - double labelIconGap; - double dropdownItemGap; - double dropdownItemTopGap; - double dropdownItemBottomGap; - double resultIconLeftGap; + final double gap; + final double labelIconGap; + final double dropdownItemGap; + final double dropdownItemTopGap; + final double dropdownItemBottomGap; + final double resultIconLeftGap; CoolDropdown({ required this.dropdownList, @@ -111,23 +112,16 @@ class CoolDropdown extends StatefulWidget { this.resultIconRotationValue = 0.5, this.isDropdownLabel = true, this.iconSize = 10, - defaultValue, + this.defaultValue, }) { - // 기본값 셋팅 - if (defaultValue != null) { - print('.. $defaultValue'); - this.defaultValue = defaultValue; - } else { - this.defaultValue = {}; - } // label unique 체크 for (var i = 0; i < dropdownList.length; i++) { - if (dropdownList[i]['label'] == null) { + if (dropdownList[i].label.isEmpty) { throw '"label" must be initialized.'; } for (var j = 0; j < dropdownList.length; j++) { if (i != j) { - if (dropdownList[i]['label'] == dropdownList[j]['label']) { + if (dropdownList[i].label == dropdownList[j].label) { throw 'label is duplicated. Labels have to be unique.'; } } @@ -195,16 +189,16 @@ class CoolDropdown extends StatefulWidget { } @override - _CoolDropdownState createState() => _CoolDropdownState(); + _CoolDropdownState createState() => _CoolDropdownState(); } -class _CoolDropdownState extends State +class _CoolDropdownState extends State> with TickerProviderStateMixin { GlobalKey dropdownBodyChild = GlobalKey(); GlobalKey inputKey = GlobalKey(); Offset triangleOffset = Offset(0, 0); late OverlayEntry _overlayEntry; - late Map selectedItem; + DropDownParams? selectedItem; late AnimationController rotationController; late AnimationController sizeController; late Animation textWidth; @@ -232,7 +226,7 @@ class _CoolDropdownState extends State OverlayEntry _createOverlayEntry() { return OverlayEntry( - builder: (BuildContext context) => DropdownBody( + builder: (BuildContext context) => DropdownBody( key: dropdownBodyChild, inputKey: inputKey, onChange: widget.onChange, @@ -371,15 +365,15 @@ class _CoolDropdownState extends State axisAlignment: -1, child: Row( mainAxisAlignment: widget.resultMainAxis, - children: [ + children: [ if (widget.isResultLabel) Flexible( child: Container( child: Text( - selectedItem['label'] ?? + selectedItem?.label ?? widget.placeholder, overflow: TextOverflow.ellipsis, - style: selectedItem['label'] != null + style: selectedItem?.label != null ? widget.resultTS : widget.placeholderTS, ), @@ -389,8 +383,8 @@ class _CoolDropdownState extends State SizedBox( width: widget.labelIconGap, ), - if (selectedItem['icon'] != null) - selectedItem['icon'] as Widget, + if (selectedItem?.icon != null) + selectedItem!.icon!, ].isReverse(widget.dropdownItemReverse), ), ), diff --git a/lib/drop_down_body.dart b/lib/drop_down_body.dart index 7a2382c..0fb10ff 100644 --- a/lib/drop_down_body.dart +++ b/lib/drop_down_body.dart @@ -1,25 +1,25 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; +import 'package:cool_dropdown/drop_down_params.dart'; import 'package:cool_dropdown/utils/animation_util.dart'; import 'package:cool_dropdown/utils/extension_util.dart'; +import 'package:flutter/material.dart'; -class DropdownBody extends StatefulWidget { +class DropdownBody extends StatefulWidget { Key key; GlobalKey inputKey; - late Function closeDropdown; + late void Function() closeDropdown; late BuildContext bodyContext; late double screenHeight; - List dropdownList; - List dropdownIsSelected = []; - Function onChange; - Function getSelectedItem; - bool isTriangle; - bool isResultLabel; - bool isDropdownLabel; - late Map selectedItem; - late Widget dropdownIcon; - bool isAnimation; + final List> dropdownList; + final List dropdownIsSelected = []; + final void Function(DropDownParams) onChange; + final void Function(DropDownParams) getSelectedItem; + final bool isTriangle; + final bool isResultLabel; + final bool isDropdownLabel; + DropDownParams? selectedItem; + late final Widget dropdownIcon; + final bool isAnimation; // size double resultWidth; @@ -142,7 +142,6 @@ class DropdownBodyState extends State late AnimationController _triangleController; List _DCController = []; List _paddingController = []; - List _swicherController = []; List> _paddingAnimation = []; late Animation animateHeight; late Animation triangleAnimation; @@ -156,7 +155,8 @@ class DropdownBodyState extends State @override void initState() { currentIndex = widget.dropdownList.indexWhere( - (dropdownItem) => mapEquals(dropdownItem, widget.selectedItem)); + (dropdownItem) => dropdownItem == widget.selectedItem, + ); setOffset(); setAnimation(); setScrollPosition(currentIndex); @@ -530,8 +530,10 @@ class DropdownBodyState extends State child: Flexible( child: Container( child: Text( - widget.dropdownList[ - index]['label'], + widget + .dropdownList[ + index] + .label, overflow: TextOverflow .ellipsis, ), @@ -546,11 +548,12 @@ class DropdownBodyState extends State width: widget.labelIconGap, ), (widget.dropdownList[index] - ['icon'] != + .icon != null && - widget.dropdownList[ - index][ - 'selectedIcon'] != + widget + .dropdownList[ + index] + .selectedIcon != null) ? AnimatedSwitcher( duration: au.isAnimation( @@ -570,27 +573,26 @@ class DropdownBodyState extends State animation); }, child: Container( - child: widget - .dropdownIsSelected[ - index] - ? widget.dropdownList[ - index] - [ - 'selectedIcon'] - as Widget - : widget.dropdownList[ - index] - ['icon'] - as Widget, - ), + child: widget + .dropdownIsSelected[ + index] + ? widget + .dropdownList[ + index] + .selectedIcon + : widget + .dropdownList[ + index] + .icon), ) : widget.dropdownList[index] - ['icon'] != + .icon != null ? Container( child: widget - .dropdownList[ - index]['icon']) + .dropdownList[ + index] + .icon) : Container(), ].isReverse( widget.dropdownItemReverse), diff --git a/lib/drop_down_params.dart b/lib/drop_down_params.dart new file mode 100644 index 0000000..eb09bae --- /dev/null +++ b/lib/drop_down_params.dart @@ -0,0 +1,15 @@ +import 'package:flutter/material.dart'; + +class DropDownParams { + DropDownParams({ + required this.label, + required this.value, + this.icon, + this.selectedIcon, + }); + + final String label; + final T value; + final Widget? icon; + final Widget? selectedIcon; +} From 3923e775e43dd2e9cebe134a97573dd09ef5c3f5 Mon Sep 17 00:00:00 2001 From: Pierre Moati Date: Fri, 23 Dec 2022 03:19:46 +0100 Subject: [PATCH 2/2] update --- lib/drop_down_body.dart | 42 ++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/lib/drop_down_body.dart b/lib/drop_down_body.dart index 0fb10ff..91daaf2 100644 --- a/lib/drop_down_body.dart +++ b/lib/drop_down_body.dart @@ -4,40 +4,40 @@ import 'package:cool_dropdown/utils/extension_util.dart'; import 'package:flutter/material.dart'; class DropdownBody extends StatefulWidget { - Key key; - GlobalKey inputKey; - late void Function() closeDropdown; - late BuildContext bodyContext; + final Key key; + final GlobalKey inputKey; + final void Function() closeDropdown; + final BuildContext bodyContext; late double screenHeight; final List> dropdownList; - final List dropdownIsSelected = []; + final List dropdownIsSelected = []; final void Function(DropDownParams) onChange; final void Function(DropDownParams) getSelectedItem; final bool isTriangle; final bool isResultLabel; final bool isDropdownLabel; - DropDownParams? selectedItem; + final DropDownParams? selectedItem; late final Widget dropdownIcon; final bool isAnimation; // size - double resultWidth; - double resultHeight; + final double resultWidth; + final double resultHeight; double? dropdownWidth; double dropdownHeight; - double dropdownItemHeight; - double triangleWidth; - double triangleHeight; + final double dropdownItemHeight; + final double triangleWidth; + final double triangleHeight; // align - Alignment resultAlign; - String dropdownAlign; - Alignment dropdownItemAlign; - String triangleAlign; - double triangleLeft; - bool dropdownItemReverse; - MainAxisAlignment dropdownItemMainAxis; + final Alignment resultAlign; + final String dropdownAlign; + final Alignment dropdownItemAlign; + final String triangleAlign; + final double triangleLeft; + final bool dropdownItemReverse; + final MainAxisAlignment dropdownItemMainAxis; // padding EdgeInsets dropdownItemPadding; @@ -60,7 +60,7 @@ class DropdownBody extends StatefulWidget { double dropdownItemBottomGap; // triangleBox Shadow - late List triangleBoxShadows; + late List triangleBoxShadows; DropdownBody( {required this.key, @@ -124,10 +124,10 @@ class DropdownBody extends StatefulWidget { } @override - DropdownBodyState createState() => DropdownBodyState(); + DropdownBodyState createState() => DropdownBodyState(); } -class DropdownBodyState extends State +class DropdownBodyState extends State> with TickerProviderStateMixin { Offset dropdownOffset = Offset(0, 0); Offset triangleOffset = Offset(0, 0);