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 {
this.backgroundColor,
this.elevation,
this.shape,
this.width,
this.child,
this.semanticLabel,
}) : assert(elevation == null || elevation >= 0.0),
......@@ -172,6 +173,12 @@ class Drawer extends StatelessWidget {
/// is also null, then it falls back to [Material]'s default.
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.
///
/// Typically a [SliverList].
......@@ -212,7 +219,7 @@ class Drawer extends StatelessWidget {
explicitChildNodes: true,
label: label,
child: ConstrainedBox(
constraints: const BoxConstraints.expand(width: _kWidth),
constraints: BoxConstraints.expand(width: width ?? drawerTheme.width ?? _kWidth),
child: Material(
color: backgroundColor ?? drawerTheme.backgroundColor,
elevation: elevation ?? drawerTheme.elevation ?? 16.0,
......
......@@ -36,6 +36,7 @@ class DrawerThemeData with Diagnosticable {
this.scrimColor,
this.elevation,
this.shape,
this.width,
});
/// Overrides the default value of [Drawer.backgroundColor].
......@@ -50,6 +51,9 @@ class DrawerThemeData with Diagnosticable {
/// Overrides the default value of [Drawer.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
/// new values.
DrawerThemeData copyWith({
......@@ -57,12 +61,14 @@ class DrawerThemeData with Diagnosticable {
Color? scrimColor,
double? elevation,
ShapeBorder? shape,
double? width,
}) {
return DrawerThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
scrimColor: scrimColor ?? this.scrimColor,
elevation: elevation ?? this.elevation,
shape: shape ?? this.shape,
width: width ?? this.width,
);
}
......@@ -80,6 +86,7 @@ class DrawerThemeData with Diagnosticable {
scrimColor: Color.lerp(a?.scrimColor, b?.scrimColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t),
shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
width: lerpDouble(a?.width, b?.width, t),
);
}
......@@ -89,6 +96,7 @@ class DrawerThemeData with Diagnosticable {
scrimColor,
elevation,
shape,
width,
);
@override
......@@ -101,7 +109,8 @@ class DrawerThemeData with Diagnosticable {
&& other.backgroundColor == backgroundColor
&& other.scrimColor == scrimColor
&& other.elevation == elevation
&& other.shape == shape;
&& other.shape == shape
&& other.width == width;
}
@override
......@@ -111,6 +120,7 @@ class DrawerThemeData with Diagnosticable {
properties.add(ColorProperty('scrimColor', scrimColor, defaultValue: null));
properties.add(DoubleProperty('elevation', elevation, defaultValue: null));
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
properties.add(DoubleProperty('width', width, defaultValue: null));
}
}
......
......@@ -445,4 +445,45 @@ void main() {
await tester.pumpAndSettle();
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() {
scrimColor: Color(0x00000098),
elevation: 5.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(2.0))),
width: 200.0,
).debugFillProperties(builder);
final List<String> description = builder.properties
......@@ -43,6 +44,7 @@ void main() {
'scrimColor: Color(0x00000098)',
'elevation: 5.0',
'shape: RoundedRectangleBorder(BorderSide(Color(0xff000000), 0.0, BorderStyle.none), BorderRadius.circular(2.0))',
'width: 200.0',
]);
});
......@@ -63,6 +65,7 @@ void main() {
expect(_drawerMaterial(tester).elevation, 16.0);
expect(_drawerMaterial(tester).shape, null);
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 {
......@@ -70,6 +73,7 @@ void main() {
const Color scrimColor = Color(0x00000002);
const double elevation = 7.0;
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
const double width = 200.0;
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
await tester.pumpWidget(
......@@ -80,6 +84,7 @@ void main() {
scrimColor: scrimColor,
elevation: elevation,
shape: shape,
width: width,
),
),
home: Scaffold(
......@@ -95,6 +100,7 @@ void main() {
expect(_drawerMaterial(tester).elevation, elevation);
expect(_drawerMaterial(tester).shape, shape);
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 {
......@@ -102,6 +108,7 @@ void main() {
const Color scrimColor = Color(0x00000002);
const double elevation = 7.0;
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
const double width = 200.0;
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
await tester.pumpWidget(
......@@ -112,6 +119,7 @@ void main() {
scrimColor: Color(0x00000004),
elevation: 13.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))),
width: 400.0,
),
),
home: Scaffold(
......@@ -121,6 +129,7 @@ void main() {
backgroundColor: backgroundColor,
elevation: elevation,
shape: shape,
width: width,
),
),
),
......@@ -132,6 +141,7 @@ void main() {
expect(_drawerMaterial(tester).elevation, elevation);
expect(_drawerMaterial(tester).shape, shape);
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 {
......@@ -139,6 +149,7 @@ void main() {
const Color scrimColor = Color(0x00000002);
const double elevation = 7.0;
const RoundedRectangleBorder shape = RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(16.0)));
const double width = 200.0;
final GlobalKey<ScaffoldState> scaffoldKey = GlobalKey<ScaffoldState>();
await tester.pumpWidget(
......@@ -149,6 +160,7 @@ void main() {
scrimColor: Color(0x00000004),
elevation: 13.0,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.all(Radius.circular(29.0))),
width: 400.0
),
),
home: DrawerTheme(
......@@ -157,6 +169,7 @@ void main() {
scrimColor: scrimColor,
elevation: elevation,
shape: shape,
width: width,
),
child: Scaffold(
key: scaffoldKey,
......@@ -172,6 +185,7 @@ void main() {
expect(_drawerMaterial(tester).elevation, elevation);
expect(_drawerMaterial(tester).shape, shape);
expect(_scrim(tester).color, scrimColor);
expect(_drawerRenderBox(tester).size.width, width);
});
}
......@@ -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