Skip to content

Commit bf577a9

Browse files
authored
Merge pull request #369 from AhmedLSayed9/support_border_radius_directional_for_menu
Support BorderRadiusDirectional for dropdown menu
2 parents f852a90 + 84b46ed commit bf577a9

File tree

4 files changed

+81
-66
lines changed

4 files changed

+81
-66
lines changed

packages/dropdown_button2/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
- Add barrierCoversButton to DropdownButtonFormField2.
1818
- Respect button's borderRadius when barrierCoversButton is false.
1919
- Respect inputDecoration's borderRadius when barrierCoversButton is false.
20+
- Support BorderRadiusDirectional for dropdown menu.
21+
- Fix barrier when using TextDirection.rtl while barrierCoversButton set to false.
2022

2123
## 3.0.0-beta.21
2224

packages/dropdown_button2/lib/src/dropdown_button2.dart

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -622,6 +622,7 @@ class _DropdownButton2State<T> extends State<DropdownButton2<T>> with WidgetsBin
622622
void _handleTap() {
623623
final NavigatorState navigator = Navigator.of(context,
624624
rootNavigator: _dropdownStyle.isFullScreen ?? _dropdownStyle.useRootNavigator);
625+
final TextDirection? textDirection = Directionality.maybeOf(context);
625626

626627
final items = widget.items!;
627628
final separator = widget.dropdownSeparator;
@@ -646,6 +647,7 @@ class _DropdownButton2State<T> extends State<DropdownButton2<T>> with WidgetsBin
646647
barrierCoversButton: widget.barrierCoversButton,
647648
parentFocusNode: _focusNode,
648649
enableFeedback: widget.enableFeedback ?? true,
650+
textDirection: textDirection,
649651
dropdownStyle: _dropdownStyle,
650652
menuItemStyle: _menuItemStyle,
651653
inputDecorationPadding: _getInputDecorationPadding(),

packages/dropdown_button2/lib/src/dropdown_menu.dart

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ class _DropdownMenuState<T> extends State<_DropdownMenu<T>> {
242242
resize: _resize,
243243
itemHeight: items[0].height,
244244
dropdownDecoration: dropdownStyle.decoration,
245+
textDirection: widget.textDirection,
245246
),
246247
child: Semantics(
247248
scopesRoute: true,
@@ -263,12 +264,13 @@ class _DropdownMenuState<T> extends State<_DropdownMenu<T>> {
263264

264265
class _DropdownMenuPainter extends CustomPainter {
265266
_DropdownMenuPainter({
266-
this.color,
267-
this.elevation,
268-
this.selectedIndex,
267+
required this.color,
268+
required this.elevation,
269+
required this.selectedIndex,
269270
required this.resize,
270271
required this.itemHeight,
271-
this.dropdownDecoration,
272+
required this.dropdownDecoration,
273+
required this.textDirection,
272274
}) : _painter = dropdownDecoration
273275
?.copyWith(
274276
color: dropdownDecoration.color ?? color,
@@ -291,6 +293,7 @@ class _DropdownMenuPainter extends CustomPainter {
291293
final Animation<double> resize;
292294
final double itemHeight;
293295
final BoxDecoration? dropdownDecoration;
296+
final TextDirection? textDirection;
294297

295298
final BoxPainter _painter;
296299

@@ -310,16 +313,21 @@ class _DropdownMenuPainter extends CustomPainter {
310313

311314
final Rect rect = Rect.fromLTRB(0.0, top.evaluate(resize), size.width, bottom.evaluate(resize));
312315

313-
_painter.paint(canvas, rect.topLeft, ImageConfiguration(size: rect.size));
316+
_painter.paint(
317+
canvas,
318+
rect.topLeft,
319+
ImageConfiguration(size: rect.size, textDirection: textDirection),
320+
);
314321
}
315322

316323
@override
317324
bool shouldRepaint(_DropdownMenuPainter oldPainter) {
318325
return oldPainter.color != color ||
319326
oldPainter.elevation != elevation ||
320327
oldPainter.selectedIndex != selectedIndex ||
321-
oldPainter.dropdownDecoration != dropdownDecoration ||
322328
oldPainter.itemHeight != itemHeight ||
329+
oldPainter.dropdownDecoration != dropdownDecoration ||
330+
oldPainter.textDirection != textDirection ||
323331
oldPainter.resize != resize;
324332
}
325333
}

packages/dropdown_button2/lib/src/dropdown_route.dart

Lines changed: 63 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
1616
required this.barrierCoversButton,
1717
required this.parentFocusNode,
1818
required this.enableFeedback,
19+
required this.textDirection,
1920
required this.dropdownStyle,
2021
required this.menuItemStyle,
2122
required this.inputDecorationPadding,
@@ -34,6 +35,7 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
3435
final TextStyle style;
3536
final FocusNode parentFocusNode;
3637
final bool enableFeedback;
38+
final TextDirection? textDirection;
3739
final DropdownStyleData dropdownStyle;
3840
final MenuItemStyleData menuItemStyle;
3941
final EdgeInsets? inputDecorationPadding;
@@ -61,46 +63,49 @@ class _DropdownRoute<T> extends PopupRoute<_DropdownRouteResult<T>> {
6163

6264
@override
6365
Widget buildPage(BuildContext context, _, __) {
64-
return FocusScope.withExternalFocusNode(
65-
focusScopeNode: _childNode,
66-
parentNode: parentFocusNode,
67-
child: LayoutBuilder(
68-
builder: (BuildContext ctx, BoxConstraints constraints) {
69-
//Exclude BottomInset from maxHeight to avoid overlapping menu items
70-
//with keyboard when using searchable dropdown.
71-
//This will ensure menu is drawn in the actual available height.
72-
final padding = MediaQuery.paddingOf(context);
73-
final viewInsets = MediaQuery.viewInsetsOf(context);
74-
final BoxConstraints actualConstraints =
75-
constraints.copyWith(maxHeight: constraints.maxHeight - viewInsets.bottom);
76-
final EdgeInsets mediaQueryPadding =
77-
dropdownStyle.useSafeArea ? padding : EdgeInsets.zero;
78-
return ValueListenableBuilder<Rect?>(
79-
valueListenable: buttonRect,
80-
builder: (BuildContext context, Rect? rect, _) {
81-
final routePage = _DropdownRoutePage<T>(
82-
route: this,
83-
constraints: actualConstraints,
84-
mediaQueryPadding: mediaQueryPadding,
85-
buttonRect: rect!,
86-
selectedIndex: selectedIndex,
87-
capturedThemes: capturedThemes,
88-
style: style,
89-
enableFeedback: enableFeedback,
90-
);
91-
return barrierCoversButton
92-
? routePage
93-
: _CustomModalBarrier(
94-
barrierColor: _altBarrierColor,
95-
animation: animation,
96-
barrierCurve: barrierCurve,
97-
buttonRect: rect,
98-
buttonBorderRadius: buttonBorderRadius ?? BorderRadius.zero,
99-
child: routePage,
100-
);
101-
},
102-
);
103-
},
66+
return Directionality(
67+
textDirection: textDirection ?? Directionality.of(context),
68+
child: FocusScope.withExternalFocusNode(
69+
focusScopeNode: _childNode,
70+
parentNode: parentFocusNode,
71+
child: LayoutBuilder(
72+
builder: (BuildContext ctx, BoxConstraints constraints) {
73+
//Exclude BottomInset from maxHeight to avoid overlapping menu items
74+
//with keyboard when using searchable dropdown.
75+
//This will ensure menu is drawn in the actual available height.
76+
final padding = MediaQuery.paddingOf(context);
77+
final viewInsets = MediaQuery.viewInsetsOf(context);
78+
final BoxConstraints actualConstraints =
79+
constraints.copyWith(maxHeight: constraints.maxHeight - viewInsets.bottom);
80+
final EdgeInsets mediaQueryPadding =
81+
dropdownStyle.useSafeArea ? padding : EdgeInsets.zero;
82+
return ValueListenableBuilder<Rect?>(
83+
valueListenable: buttonRect,
84+
builder: (BuildContext context, Rect? rect, _) {
85+
final routePage = _DropdownRoutePage<T>(
86+
route: this,
87+
constraints: actualConstraints,
88+
mediaQueryPadding: mediaQueryPadding,
89+
buttonRect: rect!,
90+
selectedIndex: selectedIndex,
91+
capturedThemes: capturedThemes,
92+
style: style,
93+
enableFeedback: enableFeedback,
94+
);
95+
return barrierCoversButton
96+
? routePage
97+
: _CustomModalBarrier(
98+
barrierColor: _altBarrierColor,
99+
animation: animation,
100+
barrierCurve: barrierCurve,
101+
buttonRect: rect,
102+
buttonBorderRadius: buttonBorderRadius ?? BorderRadius.zero,
103+
child: routePage,
104+
);
105+
},
106+
);
107+
},
108+
),
104109
),
105110
);
106111
}
@@ -503,18 +508,21 @@ class _CustomModalBarrierState extends State<_CustomModalBarrier> {
503508

504509
return Stack(
505510
children: [
506-
ValueListenableBuilder(
507-
valueListenable: color,
508-
builder: (BuildContext context, Color? value, Widget? child) {
509-
return CustomPaint(
510-
painter: _DropdownBarrierPainter(
511-
barrierColor: value,
512-
buttonRect: widget.buttonRect,
513-
buttonBorderRadius: widget.buttonBorderRadius,
514-
pageSize: size,
515-
),
516-
);
517-
},
511+
IgnorePointer(
512+
child: ValueListenableBuilder(
513+
valueListenable: color,
514+
builder: (BuildContext context, Color? value, Widget? child) {
515+
return CustomPaint(
516+
size: Size(size.width, size.height),
517+
painter: _DropdownBarrierPainter(
518+
barrierColor: value,
519+
buttonRect: widget.buttonRect,
520+
buttonBorderRadius: widget.buttonBorderRadius,
521+
pageSize: size,
522+
),
523+
);
524+
},
525+
),
518526
),
519527
widget.child,
520528
],
@@ -538,15 +546,10 @@ class _DropdownBarrierPainter extends CustomPainter {
538546
@override
539547
void paint(Canvas canvas, Size size) {
540548
if (barrierColor != null) {
541-
final Rect rect = Rect.fromLTRB(
542-
-buttonRect.left,
543-
-buttonRect.top,
544-
pageSize.width,
545-
pageSize.height,
546-
);
549+
final Rect pageRect = Offset.zero & pageSize;
547550

548-
canvas.saveLayer(rect, Paint());
549-
canvas.drawRect(rect, Paint()..color = barrierColor!);
551+
canvas.saveLayer(pageRect, Paint());
552+
canvas.drawRect(pageRect, Paint()..color = barrierColor!);
550553

551554
final RRect buttonRRect = RRect.fromRectAndCorners(
552555
buttonRect,

0 commit comments

Comments
 (0)