Skip to content

Commit 49376be

Browse files
committed
add dropdown field 2
1 parent e31d3b1 commit 49376be

7 files changed

+175
-1
lines changed

.flutter-plugins

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# This is a generated file; do not edit or check into version control.
2+
webview_flutter=/Users/haonguyen/.pub-cache/hosted/pub.dev/webview_flutter-4.2.2/
3+
webview_flutter_android=/Users/haonguyen/.pub-cache/hosted/pub.dev/webview_flutter_android-3.9.1/
4+
webview_flutter_wkwebview=/Users/haonguyen/.pub-cache/hosted/pub.dev/webview_flutter_wkwebview-3.7.1/

.flutter-plugins-dependencies

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{"info":"This is a generated file; do not edit or check into version control.","plugins":{"ios":[{"name":"webview_flutter_wkwebview","path":"/Users/haonguyen/.pub-cache/hosted/pub.dev/webview_flutter_wkwebview-3.7.1/","native_build":true,"dependencies":[]}],"android":[{"name":"webview_flutter_android","path":"/Users/haonguyen/.pub-cache/hosted/pub.dev/webview_flutter_android-3.9.1/","native_build":true,"dependencies":[]}],"macos":[],"linux":[],"windows":[],"web":[]},"dependencyGraph":[{"name":"webview_flutter","dependencies":["webview_flutter_android","webview_flutter_wkwebview"]},{"name":"webview_flutter_android","dependencies":[]},{"name":"webview_flutter_wkwebview","dependencies":[]}],"date_created":"2023-07-25 19:34:13.822748","version":"3.10.4"}

CHANGELOG.md

+6
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
## 0.1.16
2+
3+
### Added
4+
5+
* Add Dropdown Field 2
6+
17
## 0.1.15
28

39
### Added
+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
part of 'tf_form.dart';
2+
3+
/// [TFDropdownField2] widget allows the user to pick a value from a dropdown list
4+
class TFDropdownField2<T extends TFDropdonwnItem> extends StatefulWidget {
5+
TFDropdownField2({
6+
Key? key,
7+
this.title,
8+
this.hintText,
9+
required this.items,
10+
this.selectedItem,
11+
this.onChanged,
12+
this.validationTypes = const <TFValidationType>[],
13+
this.relatedController,
14+
this.style,
15+
this.enabled = true,
16+
this.showError = true,
17+
}) : super(key: key) {
18+
if (validationTypes.contains(TFValidationType.requiredIfHas) && relatedController == null) {
19+
throw ArgumentError("requiredIfHas type and relatedController should both be set.");
20+
}
21+
}
22+
23+
final String? title;
24+
final String? hintText;
25+
final List<T> items;
26+
final T? selectedItem;
27+
final Function(T selectedItem)? onChanged;
28+
final List<TFValidationType> validationTypes;
29+
final TextEditingController? relatedController;
30+
final TFFieldStyle? style;
31+
final bool enabled;
32+
final bool showError;
33+
34+
@override
35+
State<TFDropdownField2<T>> createState() => _TFDropdownFieldState2<T>();
36+
}
37+
38+
class _TFDropdownFieldState2<T extends TFDropdonwnItem> extends State<TFDropdownField2<T>> {
39+
final LayerLink _dropdownLink = LayerLink();
40+
final TextEditingController _titleController = TextEditingController();
41+
OverlayEntry? _dropdownOverlay;
42+
43+
void _showDropdown() {
44+
_dropdownOverlay = _buildDropListOverlay();
45+
Overlay.of(context).insert(_dropdownOverlay!);
46+
}
47+
48+
void _hideDropdown() {
49+
_dropdownOverlay?.remove();
50+
_dropdownOverlay = null;
51+
}
52+
53+
void _toggleDropdown() {
54+
if (_dropdownOverlay == null) {
55+
_showDropdown();
56+
} else {
57+
_hideDropdown();
58+
}
59+
}
60+
61+
@override
62+
void initState() {
63+
super.initState();
64+
_titleController.text = widget.selectedItem?.displayTitle ?? "";
65+
}
66+
67+
@override
68+
void dispose() {
69+
_titleController.dispose();
70+
_dropdownOverlay?.dispose();
71+
super.dispose();
72+
}
73+
74+
@override
75+
Widget build(BuildContext context) {
76+
return CompositedTransformTarget(
77+
link: _dropdownLink,
78+
child: TFTextField(
79+
title: widget.title,
80+
hintText: widget.hintText,
81+
controller: _titleController,
82+
validationTypes: widget.validationTypes,
83+
relatedController: widget.relatedController,
84+
readOnly: true,
85+
style: widget.style,
86+
enabled: widget.enabled,
87+
showError: widget.showError,
88+
suffix: GestureDetector(
89+
onTap: _toggleDropdown,
90+
child: const Icon(
91+
Icons.arrow_drop_down,
92+
color: Colors.grey,
93+
),
94+
),
95+
onTap: _toggleDropdown,
96+
onFocusChanged: (hasFocus) {
97+
if (!hasFocus) _hideDropdown();
98+
},
99+
),
100+
);
101+
}
102+
103+
OverlayEntry _buildDropListOverlay() {
104+
final renderBox = context.findRenderObject() as RenderBox;
105+
final size = renderBox.size;
106+
final offset = renderBox.localToGlobal(Offset.zero);
107+
final topOffset = offset.dy + size.height + 5;
108+
109+
return OverlayEntry(
110+
builder: (context) => GestureDetector(
111+
onTap: () => _hideDropdown(),
112+
behavior: HitTestBehavior.translucent,
113+
child: SizedBox(
114+
height: MediaQuery.of(context).size.height,
115+
width: MediaQuery.of(context).size.width,
116+
child: Stack(
117+
children: [
118+
Positioned(
119+
left: offset.dx,
120+
top: topOffset,
121+
width: size.width,
122+
child: CompositedTransformFollower(
123+
link: _dropdownLink,
124+
showWhenUnlinked: false,
125+
offset: Offset(0.0, size.height + 5.0),
126+
child: Material(
127+
elevation: 2,
128+
color: _tffStyle.fieldStyle.backgroundColor,
129+
child: Column(
130+
children: List.generate(widget.items.length, (index) {
131+
final item = widget.items[index];
132+
final isSelected = widget.selectedItem?.id == item.id;
133+
return ListTile(
134+
title: Text(item.displayTitle),
135+
selected: isSelected,
136+
selectedColor: Theme.of(context).colorScheme.onPrimary,
137+
selectedTileColor: Theme.of(context).colorScheme.primary,
138+
trailing: isSelected ? const Icon(Icons.check, size: 18) : null,
139+
onTap: () {
140+
widget.onChanged?.call(item);
141+
_hideDropdown();
142+
},
143+
);
144+
}),
145+
),
146+
),
147+
),
148+
),
149+
],
150+
),
151+
),
152+
),
153+
);
154+
}
155+
}

lib/src/components/tf_form.dart

+2
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ part 'tf_checkbox_group.dart';
1414

1515
part 'tf_dropdown_field.dart';
1616

17+
part 'tf_dropdown_field_2.dart';
18+
1719
part 'tf_date_field.dart';
1820

1921
part 'tf_error_text.dart';

lib/src/models/tf_option_item.dart

+6
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,9 @@ class TFOptionItem<T> {
88
final String title;
99
final T value;
1010
}
11+
12+
abstract class TFDropdonwnItem {
13+
String get displayTitle;
14+
15+
String get id;
16+
}

pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: tf_form
22
description: TechFusion's form builder and validator
3-
version: 0.1.15
3+
version: 0.1.16
44
homepage: https://github.com/TechFusionHQ/tf_form
55

66
environment:

0 commit comments

Comments
 (0)