Skip to content

Commit 5f46d8c

Browse files
authored
Merge pull request #62 from luke-genvis/a11y-fixes
[a11y] Improve the accesbility of the AdvancedDrawer widget
2 parents d688958 + 30e2b1b commit 5f46d8c

File tree

5 files changed

+118
-62
lines changed

5 files changed

+118
-62
lines changed

CHANGELOG.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,14 @@
1+
## 1.5.0
2+
3+
* Added `drawerCloseSemanticLabel` parameter to set a semantic label for the tappable area that closes the drawer.
4+
* Integrated [`Semantics`](https://api.flutter.dev/flutter/widgets/Semantics-class.html) widgets to provide better screen reader support for the drawer and example app.
5+
* Integrated [`ExcludeFocus`](https://api.flutter.dev/flutter/widgets/ExcludeFocus-class.html) and [`ExcludeSemantics`](https://api.flutter.dev/flutter/widgets/ExcludeSemantics-class.html) to widgets to dynamically control focus and semantics based on drawer visibility.
6+
* Refactored Inkwell hiding to use `Visibility`
7+
18
## 1.4.0
29

3-
* Added "initialDrawerScale" parameter to set the initial scale of the drawer.
4-
* Added "drawerSlideRatio" parameter to set the slide ratio of the drawer.
10+
* Added `initialDrawerScale` parameter to set the initial scale of the drawer.
11+
* Added `drawerSlideRatio` parameter to set the slide ratio of the drawer.
512

613
## 1.3.7
714

@@ -13,7 +20,7 @@
1320

1421
## 1.3.5
1522

16-
* Added backdrop field to set custom background
23+
* Added `backdrop` field to set custom background
1724

1825
## 1.3.4
1926

@@ -47,7 +54,7 @@
4754

4855
## 1.2.3
4956

50-
* "disabledGestures" option added to disable gestures.
57+
* `disabledGestures` option added to disable gestures.
5158

5259
## 1.2.2
5360

README.md

Lines changed: 26 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,36 @@
11
# flutter_advanced_drawer
2+
23
An advanced drawer widget, that can be fully customized with size, text, color, radius of corners.
34

45
## Advanced Drawer States
5-
| Drawer Open State | Drawer Closed State |
6-
|:-:|:-:|
6+
7+
| Drawer Open State | Drawer Closed State |
8+
| :-------------------------------------------------: | :---------------------------------------------------: |
79
| ![Advanced Drawer Open State](./PREVIEW_OPENED.png) | ![Advanced Drawer Closed State](./PREVIEW_CLOSED.png) |
810

911
## AdvancedDrawer Parameters
10-
|Parameter|Description|Type|Default|
11-
|:--------|:----------|:---|:------|
12-
|`child`|Screen widget|*Widget*|required|
13-
|`drawer`|Drawer widget|*Widget*|required|
14-
|`controller`|Widget controller|*AdvancedDrawerController*| |
15-
|`backdropColor`|Backdrop color|*Color*| |
16-
|`backdrop`|Backdrop widget for custom background|*Widget*| |
17-
|`openRatio`|Opening ratio|*double*|0.75|
18-
|`openScale`|Opening child scale factor|*double*|0.85|
19-
|`animationDuration`|Animation duration|*Duration*|300ms|
20-
|`animationCurve`|Animation curve|*Curve*|Curves.easeInOut|
21-
|`childDecoration`|Child container decoration|*BoxDecoration*|Shadow, BorderRadius|
22-
|`animateChildDecoration`|Indicates that [childDecoration] might be animated or not.|*bool*|true|
23-
|`rtlOpening`|Opening from Right-to-left.|*bool*|false|
24-
|`disabledGestures`|Disable gestures.|*bool*|false|
25-
|`initialDrawerScale`|How large the drawer segment should scale from.|*double*|0.75|
26-
|`drawerSlideRatio`|How far the drawer segment should slide with the content.|*double*|0|
12+
13+
| Parameter | Description | Type | Default |
14+
| :------------------------- | :--------------------------------------------------------- | :------------------------- | :------------------- |
15+
| `child` | Screen widget | _Widget_ | required |
16+
| `drawer` | Drawer widget | _Widget_ | required |
17+
| `controller` | Widget controller | _AdvancedDrawerController_ | |
18+
| `backdropColor` | Backdrop color | _Color_ | |
19+
| `backdrop` | Backdrop widget for custom background | _Widget_ | |
20+
| `openRatio` | Opening ratio | _double_ | 0.75 |
21+
| `openScale` | Opening child scale factor | _double_ | 0.85 |
22+
| `animationDuration` | Animation duration | _Duration_ | 300ms |
23+
| `animationCurve` | Animation curve | _Curve_ | Curves.easeInOut |
24+
| `childDecoration` | Child container decoration | _BoxDecoration_ | Shadow, BorderRadius |
25+
| `animateChildDecoration` | Indicates that [childDecoration] might be animated or not. | _bool_ | true |
26+
| `rtlOpening` | Opening from Right-to-left. | _bool_ | false |
27+
| `disabledGestures` | Disable gestures. | _bool_ | false |
28+
| `initialDrawerScale` | How large the drawer segment should scale from. | _double_ | 0.75 |
29+
| `drawerSlideRatio` | How far the drawer segment should slide with the content. | _double_ | 0 |
30+
| `drawerCloseSemanticLabel` | Semantic label for the close drawer button. | _String_ | 'Close drawer' |
2731

2832
## Preview
29-
| Preview Tap | Preview Gesture |
30-
|:-:|:-:|
33+
34+
| Preview Tap | Preview Gesture |
35+
| :-------------------------------------------------: | :------------------------------------------------: |
3136
| ![Advanced Drawer Tap Animation](./PREVIEW_TAP.gif) | ![Advanced Drawer Gestures](./PREVIEW_GESTURE.gif) |

example/lib/main.dart

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,13 @@ class _HomeScreenState extends State<HomeScreen> {
6464
builder: (_, value, __) {
6565
return AnimatedSwitcher(
6666
duration: Duration(milliseconds: 250),
67-
child: Icon(
68-
value.visible ? Icons.clear : Icons.menu,
69-
key: ValueKey<bool>(value.visible),
67+
child: Semantics(
68+
label: 'Menu',
69+
onTapHint: 'expand drawer',
70+
child: Icon(
71+
value.visible ? Icons.clear : Icons.menu,
72+
key: ValueKey<bool>(value.visible),
73+
),
7074
),
7175
);
7276
},

lib/src/widget.dart

Lines changed: 72 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ class AdvancedDrawer extends StatefulWidget {
2020
this.rtlOpening = false,
2121
this.disabledGestures = false,
2222
this.animationController,
23+
this.drawerCloseSemanticLabel = 'Close drawer',
2324
}) : super(key: key);
2425

2526
/// Child widget. (Usually widget that represent a screen)
@@ -74,6 +75,14 @@ class AdvancedDrawer extends StatefulWidget {
7475
/// Controller that controls widget animation.
7576
final AnimationController? animationController;
7677

78+
/// Provides a textual description of the close drawer action.
79+
///
80+
/// This is used by accessibility frameworks to provide context
81+
/// for screen readers of what the close drawer action will do.
82+
///
83+
/// if null, it will default to `'Close drawer'`
84+
final String? drawerCloseSemanticLabel;
85+
7786
@override
7887
_AdvancedDrawerState createState() => _AdvancedDrawerState();
7988
}
@@ -127,25 +136,45 @@ class _AdvancedDrawerState extends State<AdvancedDrawer>
127136
color: Colors.transparent,
128137
child: Stack(
129138
children: [
130-
if (widget.backdrop != null) widget.backdrop!,
131-
Align(
132-
alignment: widget.rtlOpening
133-
? Alignment.centerRight
134-
: Alignment.centerLeft,
135-
child: SlideTransition(
136-
position: _drawerSlideAnimation,
137-
child: FractionallySizedBox(
138-
widthFactor: widget.openRatio,
139-
child: ScaleTransition(
140-
scale: _drawerScaleAnimation,
139+
ValueListenableBuilder<AdvancedDrawerValue>(
140+
valueListenable: _controller,
141+
builder: (_, value, child) {
142+
return ExcludeFocus(
143+
excluding: !value.visible,
144+
child: ExcludeSemantics(
145+
excluding: !value.visible,
146+
child: child,
147+
),
148+
);
149+
},
150+
child: Stack(
151+
children: [
152+
if (widget.backdrop != null) widget.backdrop!,
153+
Align(
141154
alignment: widget.rtlOpening
142-
? Alignment.centerLeft
143-
: Alignment.centerRight,
144-
child: RepaintBoundary(
145-
child: widget.drawer,
155+
? Alignment.centerRight
156+
: Alignment.centerLeft,
157+
child: SlideTransition(
158+
position: _drawerSlideAnimation,
159+
child: FractionallySizedBox(
160+
widthFactor: widget.openRatio,
161+
child: ScaleTransition(
162+
scale: _drawerScaleAnimation,
163+
alignment: widget.rtlOpening
164+
? Alignment.centerLeft
165+
: Alignment.centerRight,
166+
child: RepaintBoundary(
167+
child: Semantics(
168+
container: true,
169+
explicitChildNodes: true,
170+
child: widget.drawer,
171+
),
172+
),
173+
),
174+
),
146175
),
147176
),
148-
),
177+
],
149178
),
150179
),
151180
SlideTransition(
@@ -157,29 +186,38 @@ class _AdvancedDrawerState extends State<AdvancedDrawer>
157186
? Alignment.centerRight
158187
: Alignment.centerLeft,
159188
scale: _childScaleAnimation,
160-
child: Builder(
161-
builder: (_) {
189+
child: ValueListenableBuilder<AdvancedDrawerValue>(
190+
valueListenable: _controller,
191+
child: widget.child,
192+
builder: (_, value, child) {
162193
final childStack = Stack(
163194
children: [
164-
RepaintBoundary(child: widget.child),
165-
ValueListenableBuilder<AdvancedDrawerValue>(
166-
valueListenable: _controller,
167-
builder: (_, value, __) {
168-
if (!value.visible) {
169-
return const SizedBox();
170-
}
171-
172-
return Material(
173-
color: Colors.transparent,
195+
ExcludeFocus(
196+
excluding: value.visible,
197+
child: ExcludeSemantics(
198+
excluding: value.visible,
199+
child: RepaintBoundary(
200+
child: child,
201+
),
202+
),
203+
),
204+
Visibility(
205+
visible: value.visible,
206+
child: Material(
207+
color: Colors.transparent,
208+
child: Semantics(
209+
label: widget.drawerCloseSemanticLabel,
210+
button: true,
211+
container: true,
174212
child: InkWell(
175213
onTap: _controller.hideDrawer,
176214
splashColor: Colors.transparent,
177215
highlightColor: Colors.transparent,
178216
child: Container(),
179217
),
180-
);
181-
},
182-
),
218+
),
219+
),
220+
)
183221
],
184222
);
185223

@@ -273,7 +311,9 @@ class _AdvancedDrawerState extends State<AdvancedDrawer>
273311
// If widget is not mounted do nothing
274312
if (!mounted) return;
275313
// If the value of _controller is visible, forward the animation; otherwise, reverse it
276-
_controller.value.visible ? _animationController.forward() : _animationController.reverse();
314+
_controller.value.visible
315+
? _animationController.forward()
316+
: _animationController.reverse();
277317
}
278318

279319
void _handleDragStart(DragStartDetails details) {

pubspec.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
name: flutter_advanced_drawer
22
description: An advanced drawer widget, that can be fully customized with size, text, color, radius of corners.
3-
version: 1.4.0
3+
version: 1.5.0
44
homepage: https://github.com/alex-melnyk/flutter_advanced_drawer
55
repository: https://github.com/alex-melnyk/flutter_advanced_drawer
66
issue_tracker: https://github.com/alex-melnyk/flutter_advanced_drawer/issues
77
documentation: https://github.com/alex-melnyk/flutter_advanced_drawer/blob/master/README.md
88

99
environment:
10-
sdk: '>=2.12.0 <3.0.0'
10+
sdk: ">=2.12.0 <3.0.0"
1111

1212
dependencies:
1313
flutter:

0 commit comments

Comments
 (0)