Unverified Commit 72080650 authored by Tyler Holland's avatar Tyler Holland Committed by GitHub

Allow Drawer width to be customized (#99777)

* Add ability to customize Drawer width

* Fix formatting

* More formatting

* Formatting again

* Add width to DrawerThemeData and add associated tests

* Fix test formatting
parent b4247365
...@@ -144,6 +144,7 @@ class Drawer extends StatelessWidget { ...@@ -144,6 +144,7 @@ class Drawer extends StatelessWidget {
this.backgroundColor, this.backgroundColor,
this.elevation, this.elevation,
this.shape, this.shape,
this.width,
this.child, this.child,
this.semanticLabel, this.semanticLabel,
}) : assert(elevation == null || elevation >= 0.0), }) : assert(elevation == null || elevation >= 0.0),
...@@ -172,6 +173,12 @@ class Drawer extends StatelessWidget { ...@@ -172,6 +173,12 @@ class Drawer extends StatelessWidget {
/// is also null, then it falls back to [Material]'s default. /// is also null, then it falls back to [Material]'s default.
final ShapeBorder? shape; final ShapeBorder? shape;
/// The width of the drawer.
///
/// If this is null, then [DrawerThemeData.width] is used. If that is also
/// null, then it falls back to the Material spec's default (304.0).
final double? width;
/// The widget below this widget in the tree. /// The widget below this widget in the tree.
/// ///
/// Typically a [SliverList]. /// Typically a [SliverList].
...@@ -212,7 +219,7 @@ class Drawer extends StatelessWidget { ...@@ -212,7 +219,7 @@ class Drawer extends StatelessWidget {
explicitChildNodes: true, explicitChildNodes: true,
label: label, label: label,
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints.expand(width: _kWidth), constraints: BoxConstraints.expand(width: width ?? drawerTheme.width ?? _kWidth),
child: Material( child: Material(
color: backgroundColor ?? drawerTheme.backgroundColor, color: backgroundColor ?? drawerTheme.backgroundColor,
elevation: elevation ?? drawerTheme.elevation ?? 16.0, elevation: elevation ?? drawerTheme.elevation ?? 16.0,
......
...@@ -36,6 +36,7 @@ class DrawerThemeData with Diagnosticable { ...@@ -36,6 +36,7 @@ class DrawerThemeData with Diagnosticable {
this.scrimColor, this.scrimColor,
this.elevation, this.elevation,
this.shape, this.shape,
this.width,
}); });
/// Overrides the default value of [Drawer.backgroundColor]. /// Overrides the default value of [Drawer.backgroundColor].
...@@ -50,6 +51,9 @@ class DrawerThemeData with Diagnosticable { ...@@ -50,6 +51,9 @@ class DrawerThemeData with Diagnosticable {
/// Overrides the default value of [Drawer.shape]. /// Overrides the default value of [Drawer.shape].
final ShapeBorder? shape; final ShapeBorder? shape;
/// Overrides the default value of [Drawer.width].
final double? width;
/// Creates a copy of this object with the given fields replaced with the /// Creates a copy of this object with the given fields replaced with the
/// new values. /// new values.
DrawerThemeData copyWith({ DrawerThemeData copyWith({
...@@ -57,12 +61,14 @@ class DrawerThemeData with Diagnosticable { ...@@ -57,12 +61,14 @@ class DrawerThemeData with Diagnosticable {
Color? scrimColor, Color? scrimColor,
double? elevation, double? elevation,
ShapeBorder? shape, ShapeBorder? shape,
double? width,
}) { }) {
return DrawerThemeData( return DrawerThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor, backgroundColor: backgroundColor ?? this.backgroundColor,
scrimColor: scrimColor ?? this.scrimColor, scrimColor: scrimColor ?? this.scrimColor,
elevation: elevation ?? this.elevation, elevation: elevation ?? this.elevation,
shape: shape ?? this.shape, shape: shape ?? this.shape,
width: width ?? this.width,
); );
} }
...@@ -80,6 +86,7 @@ class DrawerThemeData with Diagnosticable { ...@@ -80,6 +86,7 @@ class DrawerThemeData with Diagnosticable {
scrimColor: Color.lerp(a?.scrimColor, b?.scrimColor, t), scrimColor: Color.lerp(a?.scrimColor, b?.scrimColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t), elevation: lerpDouble(a?.elevation, b?.elevation, t),
shape: ShapeBorder.lerp(a?.shape, b?.shape, t), shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
width: lerpDouble(a?.width, b?.width, t),
); );
} }
...@@ -89,6 +96,7 @@ class DrawerThemeData with Diagnosticable { ...@@ -89,6 +96,7 @@ class DrawerThemeData with Diagnosticable {
scrimColor, scrimColor,
elevation, elevation,
shape, shape,
width,
); );
@override @override
...@@ -101,7 +109,8 @@ class DrawerThemeData with Diagnosticable { ...@@ -101,7 +109,8 @@ class DrawerThemeData with Diagnosticable {
&& other.backgroundColor == backgroundColor && other.backgroundColor == backgroundColor
&& other.scrimColor == scrimColor && other.scrimColor == scrimColor
&& other.elevation == elevation && other.elevation == elevation
&& other.shape == shape; && other.shape == shape
&& other.width == width;
} }
@override @override
...@@ -111,6 +120,7 @@ class DrawerThemeData with Diagnosticable { ...@@ -111,6 +120,7 @@ class DrawerThemeData with Diagnosticable {
properties.add(ColorProperty('scrimColor', scrimColor, defaultValue: null)); properties.add(ColorProperty('scrimColor', scrimColor, defaultValue: null));
properties.add(DoubleProperty('elevation', elevation, defaultValue: null)); properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null)); properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
properties.add(DoubleProperty('width', width, defaultValue: null));
} }
} }
......
...@@ -445,4 +445,45 @@ void main() { ...@@ -445,4 +445,45 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
expect(find.text('endDrawer'), findsNothing); expect(find.text('endDrawer'), findsNothing);
}); });
testWidgets('Drawer width defaults to Material spec', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
drawer: Drawer(),
),
),
);
final ScaffoldState state = tester.firstState(find.byType(Scaffold));
state.openDrawer();
await tester.pump();
await tester.pump(const Duration(seconds: 1));
final RenderBox box = tester.renderObject(find.byType(Drawer));
expect(box.size.width, equals(304.0));
});
testWidgets('Drawer width can be customized by parameter', (WidgetTester tester) async {
const double smallWidth = 200;
await tester.pumpWidget(
const MaterialApp(
home: Scaffold(
drawer: Drawer(
width: smallWidth,
),
),
),
);
final ScaffoldState state = tester.firstState(find.byType(Scaffold));
state.openDrawer();
await tester.pumpAndSettle();
final RenderBox box = tester.renderObject(find.byType(Drawer));
expect(box.size.width, equals(smallWidth));
});
} }
...@@ -31,6 +31,7 @@ void main() { ...@@ -31,6 +31,7 @@ void main() {
scrimColor: Color(0x00000098), scrimColor: Color(0x00000098),
elevation: 5.0, elevation: 5.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))), shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))),
width: 200.0,
).debugFillProperties(builder); ).debugFillProperties(builder);
final List<String> description = builder.properties final List<String> description = builder.properties
...@@ -43,6 +44,7 @@ void main() { ...@@ -43,6 +44,7 @@ void main() {
'scrimColor: Color(0x00000098)', 'scrimColor: Color(0x00000098)',
'elevation: 5.0', 'elevation: 5.0',
'shape: RoundedRectangleBorder(BorderSide(Color(0xff000000), 0.0, BorderStyle.none), BorderRadius.circular(2.0))', 'shape: RoundedRectangleBorder(BorderSide(Color(0xff000000), 0.0, BorderStyle.none), BorderRadius.circular(2.0))',
'width: 200.0',
]); ]);
}); });
...@@ -63,6 +65,7 @@ void main() { ...@@ -63,6 +65,7 @@ void main() {
expect(_drawerMaterial(tester).elevation, 16.0); expect(_drawerMaterial(tester).elevation, 16.0);
expect(_drawerMaterial(tester).shape, null); expect(_drawerMaterial(tester).shape, null);
expect(_scrim(tester).color, Colors.black54); expect(_scrim(tester).color, Colors.black54);
expect(_drawerRenderBox(tester).size.width, 304.0);
}); });
testWidgets('DrawerThemeData values are used when no Drawer properties are specified', (WidgetTester tester) async { testWidgets('DrawerThemeData values are used when no Drawer properties are specified', (WidgetTester tester) async {
...@@ -70,6 +73,7 @@ void main() { ...@@ -70,6 +73,7 @@ void main() {
const Color scrimColor = Color(0x00000002); const Color scrimColor = Color(0x00000002);
const double elevation = 7.0; const double elevation = 7.0;
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0))); const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
const double width = 200.0;
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
await tester.pumpWidget( await tester.pumpWidget(
...@@ -80,6 +84,7 @@ void main() { ...@@ -80,6 +84,7 @@ void main() {
scrimColor: scrimColor, scrimColor: scrimColor,
elevation: elevation, elevation: elevation,
shape: shape, shape: shape,
width: width,
), ),
), ),
home: Scaffold( home: Scaffold(
...@@ -95,6 +100,7 @@ void main() { ...@@ -95,6 +100,7 @@ void main() {
expect(_drawerMaterial(tester).elevation, elevation); expect(_drawerMaterial(tester).elevation, elevation);
expect(_drawerMaterial(tester).shape, shape); expect(_drawerMaterial(tester).shape, shape);
expect(_scrim(tester).color, scrimColor); expect(_scrim(tester).color, scrimColor);
expect(_drawerRenderBox(tester).size.width, width);
}); });
testWidgets('Drawer values take priority over DrawerThemeData values when both properties are specified', (WidgetTester tester) async { testWidgets('Drawer values take priority over DrawerThemeData values when both properties are specified', (WidgetTester tester) async {
...@@ -102,6 +108,7 @@ void main() { ...@@ -102,6 +108,7 @@ void main() {
const Color scrimColor = Color(0x00000002); const Color scrimColor = Color(0x00000002);
const double elevation = 7.0; const double elevation = 7.0;
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0))); const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
const double width = 200.0;
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
await tester.pumpWidget( await tester.pumpWidget(
...@@ -112,6 +119,7 @@ void main() { ...@@ -112,6 +119,7 @@ void main() {
scrimColor: Color(0x00000004), scrimColor: Color(0x00000004),
elevation: 13.0, elevation: 13.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))), shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))),
width: 400.0,
), ),
), ),
home: Scaffold( home: Scaffold(
...@@ -121,6 +129,7 @@ void main() { ...@@ -121,6 +129,7 @@ void main() {
backgroundColor: backgroundColor, backgroundColor: backgroundColor,
elevation: elevation, elevation: elevation,
shape: shape, shape: shape,
width: width,
), ),
), ),
), ),
...@@ -132,6 +141,7 @@ void main() { ...@@ -132,6 +141,7 @@ void main() {
expect(_drawerMaterial(tester).elevation, elevation); expect(_drawerMaterial(tester).elevation, elevation);
expect(_drawerMaterial(tester).shape, shape); expect(_drawerMaterial(tester).shape, shape);
expect(_scrim(tester).color, scrimColor); expect(_scrim(tester).color, scrimColor);
expect(_drawerRenderBox(tester).size.width, width);
}); });
testWidgets('DrawerTheme values take priority over ThemeData.drawerTheme values when both properties are specified', (WidgetTester tester) async { testWidgets('DrawerTheme values take priority over ThemeData.drawerTheme values when both properties are specified', (WidgetTester tester) async {
...@@ -139,6 +149,7 @@ void main() { ...@@ -139,6 +149,7 @@ void main() {
const Color scrimColor = Color(0x00000002); const Color scrimColor = Color(0x00000002);
const double elevation = 7.0; const double elevation = 7.0;
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0))); const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
const double width = 200.0;
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
await tester.pumpWidget( await tester.pumpWidget(
...@@ -149,6 +160,7 @@ void main() { ...@@ -149,6 +160,7 @@ void main() {
scrimColor: Color(0x00000004), scrimColor: Color(0x00000004),
elevation: 13.0, elevation: 13.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))), shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))),
width: 400.0
), ),
), ),
home: DrawerTheme( home: DrawerTheme(
...@@ -157,6 +169,7 @@ void main() { ...@@ -157,6 +169,7 @@ void main() {
scrimColor: scrimColor, scrimColor: scrimColor,
elevation: elevation, elevation: elevation,
shape: shape, shape: shape,
width: width,
), ),
child: Scaffold( child: Scaffold(
key: scaffoldKey, key: scaffoldKey,
...@@ -172,6 +185,7 @@ void main() { ...@@ -172,6 +185,7 @@ void main() {
expect(_drawerMaterial(tester).elevation, elevation); expect(_drawerMaterial(tester).elevation, elevation);
expect(_drawerMaterial(tester).shape, shape); expect(_drawerMaterial(tester).shape, shape);
expect(_scrim(tester).color, scrimColor); expect(_scrim(tester).color, scrimColor);
expect(_drawerRenderBox(tester).size.width, width);
}); });
} }
...@@ -200,3 +214,8 @@ Container _scrim(WidgetTester tester) { ...@@ -200,3 +214,8 @@ Container _scrim(WidgetTester tester) {
), ),
); );
} }
// The RenderBox representing the Drawer.
RenderBox _drawerRenderBox(WidgetTester tester) {
return tester.renderObject(find.byType(Drawer));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment