Skip to content

Commit a157df1

Browse files
author
Christoph Bühler
committed
feat: add close on outside tag flag
1 parent 4cebc7a commit a157df1

File tree

2 files changed

+54
-36
lines changed

2 files changed

+54
-36
lines changed

example/lib/main.dart

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ void main() {
8383
description: 'The direction where the dropdown should open to.',
8484
initial: DropdownDirection.downRight,
8585
options: DropdownDirection.values.map((v) => Option(label: v.name, value: v)).toList()),
86+
closeOnOutsideTap: context.knobs.boolean(
87+
label: 'Close On Outside Tap',
88+
description:
89+
'Whether the content is closed on an outside tap or only if the content calls close().',
90+
initial: true),
8691
)));
8792
})
8893
],

lib/src/generic_dropdown.dart

Lines changed: 49 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -88,12 +88,17 @@ class GenericDropdown extends StatefulWidget {
8888
/// [DropdownDirection]. Defaults to [Offset.zero].
8989
final Offset offset;
9090

91+
/// Whether the content should close if any click/tap happens
92+
/// outside the content container. Defaults to `true`.
93+
final bool closeOnOutsideTap;
94+
9195
const GenericDropdown(
9296
{super.key,
9397
required this.contentBuilder,
9498
this.anchor = DropdownAnchor.bottomLeft,
9599
this.direction = DropdownDirection.downRight,
96100
required this.toggleBuilder,
101+
this.closeOnOutsideTap = true,
97102
this.offset = Offset.zero});
98103

99104
@override
@@ -149,70 +154,70 @@ class _GenericDropdownState extends State<GenericDropdown> {
149154

150155
// Anchor TOP LEFT
151156
if (widget.anchor == DropdownAnchor.topLeft && widget.direction == DropdownDirection.upLeft) {
152-
bottom = screenSize.height - togglePosition.dy + (widget.offset?.dy ?? 0);
153-
right = screenSize.width - togglePosition.dx + (widget.offset?.dx ?? 0);
157+
bottom = screenSize.height - togglePosition.dy + widget.offset.dy;
158+
right = screenSize.width - togglePosition.dx + widget.offset.dx;
154159
} else if (widget.anchor == DropdownAnchor.topLeft && widget.direction == DropdownDirection.upRight) {
155-
bottom = screenSize.height - togglePosition.dy + (widget.offset?.dy ?? 0);
156-
left = togglePosition.dx + (widget.offset?.dx ?? 0);
160+
bottom = screenSize.height - togglePosition.dy + widget.offset.dy;
161+
left = togglePosition.dx + widget.offset.dx;
157162
} else if (widget.anchor == DropdownAnchor.topLeft && widget.direction == DropdownDirection.downLeft) {
158-
top = togglePosition.dy + (widget.offset?.dy ?? 0);
159-
right = screenSize.width - togglePosition.dx + (widget.offset?.dx ?? 0);
163+
top = togglePosition.dy + widget.offset.dy;
164+
right = screenSize.width - togglePosition.dx + widget.offset.dx;
160165
} else if (widget.anchor == DropdownAnchor.topLeft && widget.direction == DropdownDirection.downRight) {
161-
top = togglePosition.dy + (widget.offset?.dy ?? 0);
162-
left = togglePosition.dx + (widget.offset?.dx ?? 0);
166+
top = togglePosition.dy + widget.offset.dy;
167+
left = togglePosition.dx + widget.offset.dx;
163168
}
164169

165170
// Anchor TOP RIGHT
166171
if (widget.anchor == DropdownAnchor.topRight && widget.direction == DropdownDirection.upLeft) {
167-
bottom = screenSize.height - togglePosition.dy + (widget.offset?.dy ?? 0);
168-
right = screenSize.width - togglePosition.dx + (widget.offset?.dx ?? 0) - size.width;
172+
bottom = screenSize.height - togglePosition.dy + widget.offset.dy;
173+
right = screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
169174
} else if (widget.anchor == DropdownAnchor.topRight && widget.direction == DropdownDirection.upRight) {
170-
bottom = screenSize.height - togglePosition.dy + (widget.offset?.dy ?? 0);
171-
left = togglePosition.dx + (widget.offset?.dx ?? 0) + size.width;
175+
bottom = screenSize.height - togglePosition.dy + widget.offset.dy;
176+
left = togglePosition.dx + widget.offset.dx + size.width;
172177
} else if (widget.anchor == DropdownAnchor.topRight && widget.direction == DropdownDirection.downLeft) {
173-
top = togglePosition.dy + (widget.offset?.dy ?? 0);
174-
right = screenSize.width - togglePosition.dx + (widget.offset?.dx ?? 0) - size.width;
178+
top = togglePosition.dy + widget.offset.dy;
179+
right = screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
175180
} else if (widget.anchor == DropdownAnchor.topRight && widget.direction == DropdownDirection.downRight) {
176-
top = togglePosition.dy + (widget.offset?.dy ?? 0);
177-
left = togglePosition.dx + (widget.offset?.dx ?? 0) + size.width;
181+
top = togglePosition.dy + widget.offset.dy;
182+
left = togglePosition.dx + widget.offset.dx + size.width;
178183
}
179184

180185
// Anchor BOTTOM LEFT
181186
if (widget.anchor == DropdownAnchor.bottomLeft && widget.direction == DropdownDirection.upLeft) {
182-
bottom = screenSize.height - togglePosition.dy + (widget.offset?.dy ?? 0) - size.height;
183-
right = screenSize.width - togglePosition.dx + (widget.offset?.dx ?? 0);
187+
bottom = screenSize.height - togglePosition.dy + widget.offset.dy - size.height;
188+
right = screenSize.width - togglePosition.dx + widget.offset.dx;
184189
} else if (widget.anchor == DropdownAnchor.bottomLeft && widget.direction == DropdownDirection.upRight) {
185-
bottom = screenSize.height - togglePosition.dy + (widget.offset?.dy ?? 0) - size.height;
186-
left = togglePosition.dx + (widget.offset?.dx ?? 0);
190+
bottom = screenSize.height - togglePosition.dy + widget.offset.dy - size.height;
191+
left = togglePosition.dx + widget.offset.dx;
187192
} else if (widget.anchor == DropdownAnchor.bottomLeft && widget.direction == DropdownDirection.downLeft) {
188-
top = togglePosition.dy + (widget.offset?.dy ?? 0) + size.height;
189-
right = screenSize.width - togglePosition.dx + (widget.offset?.dx ?? 0);
193+
top = togglePosition.dy + widget.offset.dy + size.height;
194+
right = screenSize.width - togglePosition.dx + widget.offset.dx;
190195
} else if (widget.anchor == DropdownAnchor.bottomLeft && widget.direction == DropdownDirection.downRight) {
191-
top = togglePosition.dy + (widget.offset?.dy ?? 0) + size.height;
192-
left = togglePosition.dx + (widget.offset?.dx ?? 0);
196+
top = togglePosition.dy + widget.offset.dy + size.height;
197+
left = togglePosition.dx + widget.offset.dx;
193198
}
194199

195200
// Anchor BOTTOM RIGHT
196201
if (widget.anchor == DropdownAnchor.bottomRight && widget.direction == DropdownDirection.upLeft) {
197-
bottom = screenSize.height - togglePosition.dy + (widget.offset?.dy ?? 0) - size.height;
198-
right = screenSize.width - togglePosition.dx + (widget.offset?.dx ?? 0) - size.width;
202+
bottom = screenSize.height - togglePosition.dy + widget.offset.dy - size.height;
203+
right = screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
199204
} else if (widget.anchor == DropdownAnchor.bottomRight && widget.direction == DropdownDirection.upRight) {
200-
bottom = screenSize.height - togglePosition.dy + (widget.offset?.dy ?? 0) - size.height;
201-
left = togglePosition.dx + (widget.offset?.dx ?? 0) + size.width;
205+
bottom = screenSize.height - togglePosition.dy + widget.offset.dy - size.height;
206+
left = togglePosition.dx + widget.offset.dx + size.width;
202207
} else if (widget.anchor == DropdownAnchor.bottomRight && widget.direction == DropdownDirection.downLeft) {
203-
top = togglePosition.dy + (widget.offset?.dy ?? 0) + size.height;
204-
right = screenSize.width - togglePosition.dx + (widget.offset?.dx ?? 0) - size.width;
208+
top = togglePosition.dy + widget.offset.dy + size.height;
209+
right = screenSize.width - togglePosition.dx + widget.offset.dx - size.width;
205210
} else if (widget.anchor == DropdownAnchor.bottomRight && widget.direction == DropdownDirection.downRight) {
206-
top = togglePosition.dy + (widget.offset?.dy ?? 0) + size.height;
207-
left = togglePosition.dx + (widget.offset?.dx ?? 0) + size.width;
211+
top = togglePosition.dy + widget.offset.dy + size.height;
212+
left = togglePosition.dx + widget.offset.dx + size.width;
208213
}
209214

210215
_overlayEntry = OverlayEntry(
211216
maintainState: true,
212217
builder: (context) => Material(
213218
color: Colors.transparent,
214219
child: GestureDetector(
215-
onTap: _close,
220+
onTap: () => widget.closeOnOutsideTap ? _close() : null,
216221
child: Container(
217222
alignment: Alignment.topLeft,
218223
color: Colors.transparent,
@@ -223,9 +228,17 @@ class _GenericDropdownState extends State<GenericDropdown> {
223228
left: left,
224229
bottom: bottom,
225230
right: right,
226-
child: StatefulBuilder(
227-
builder: (context, setState) =>
228-
widget.contentBuilder.call(context, () => setState(() {}), _close)),
231+
child: GestureDetector(
232+
onTap: () {
233+
// this gesture detector prevents
234+
// the bubbling event that closes the
235+
// content on a click inside the
236+
// content.
237+
},
238+
child: StatefulBuilder(
239+
builder: (context, setState) =>
240+
widget.contentBuilder.call(context, () => setState(() {}), _close)),
241+
),
229242
),
230243
],
231244
),

0 commit comments

Comments
 (0)