From ae847d9730af8d59d746e0b04ef30a1767c11103 Mon Sep 17 00:00:00 2001 From: lisa-liao Date: Thu, 22 Aug 2019 10:58:39 -0700 Subject: [PATCH] Allow independent theming of Persistent and Modal bottom sheets (#38650) BottomSheetThemeData has an additional field modalElevation which makes it possible to set different elevations between persistent and modal bottom sheets. --- .../lib/src/material/bottom_sheet.dart | 2 +- .../lib/src/material/bottom_sheet_theme.dart | 13 ++ .../material/bottom_sheet_theme_test.dart | 113 +++++++++++++++++- 3 files changed, 124 insertions(+), 4 deletions(-) diff --git a/packages/flutter/lib/src/material/bottom_sheet.dart b/packages/flutter/lib/src/material/bottom_sheet.dart index ec7cede960..cd7e80a66b 100644 --- a/packages/flutter/lib/src/material/bottom_sheet.dart +++ b/packages/flutter/lib/src/material/bottom_sheet.dart @@ -462,7 +462,7 @@ Future showModalBottomSheet({ isScrollControlled: isScrollControlled, barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel, backgroundColor: backgroundColor, - elevation: elevation, + elevation: elevation ?? Theme.of(context).bottomSheetTheme.modalElevation, shape: shape, clipBehavior: clipBehavior, )); diff --git a/packages/flutter/lib/src/material/bottom_sheet_theme.dart b/packages/flutter/lib/src/material/bottom_sheet_theme.dart index fcf0fd7500..bdb1db5df7 100644 --- a/packages/flutter/lib/src/material/bottom_sheet_theme.dart +++ b/packages/flutter/lib/src/material/bottom_sheet_theme.dart @@ -29,6 +29,7 @@ class BottomSheetThemeData extends Diagnosticable { const BottomSheetThemeData({ this.backgroundColor, this.elevation, + this.modalElevation, this.shape, this.clipBehavior, }); @@ -45,6 +46,12 @@ class BottomSheetThemeData extends Diagnosticable { /// If null, [BottomSheet] defaults to 0.0. final double elevation; + /// Value for [BottomSheet.elevation] when the Bottom sheet is presented as a + /// modal bottom sheet. + /// + /// If null, [BottomSheet.elevation] defaults to [elevation]. + final double modalElevation; + /// Default value for [BottomSheet.shape]. /// /// If null, no overriding shape is specified for [BottomSheet], so the @@ -61,12 +68,14 @@ class BottomSheetThemeData extends Diagnosticable { BottomSheetThemeData copyWith({ Color backgroundColor, double elevation, + double modalElevation, ShapeBorder shape, Clip clipBehavior, }) { return BottomSheetThemeData( backgroundColor: backgroundColor ?? this.backgroundColor, elevation: elevation ?? this.elevation, + modalElevation: modalElevation ?? this.modalElevation, shape: shape ?? this.shape, clipBehavior: clipBehavior ?? this.clipBehavior, ); @@ -84,6 +93,7 @@ class BottomSheetThemeData extends Diagnosticable { return BottomSheetThemeData( backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t), elevation: lerpDouble(a?.elevation, b?.elevation, t), + modalElevation: lerpDouble(a?.modalElevation, b?.modalElevation, t), shape: ShapeBorder.lerp(a?.shape, b?.shape, t), clipBehavior: t < 0.5 ? a?.clipBehavior : b?.clipBehavior, ); @@ -94,6 +104,7 @@ class BottomSheetThemeData extends Diagnosticable { return hashValues( backgroundColor, elevation, + modalElevation, shape, clipBehavior, ); @@ -108,6 +119,7 @@ class BottomSheetThemeData extends Diagnosticable { final BottomSheetThemeData typedOther = other; return typedOther.backgroundColor == backgroundColor && typedOther.elevation == elevation + && typedOther.modalElevation == modalElevation && typedOther.shape == shape && typedOther.clipBehavior == clipBehavior; } @@ -117,6 +129,7 @@ class BottomSheetThemeData extends Diagnosticable { super.debugFillProperties(properties); properties.add(ColorProperty('backgroundColor', backgroundColor, defaultValue: null)); properties.add(DoubleProperty('elevation', elevation, defaultValue: null)); + properties.add(DoubleProperty('modalElevation', modalElevation, defaultValue: null)); properties.add(DiagnosticsProperty('shape', shape, defaultValue: null)); properties.add(DiagnosticsProperty('clipBehavior', clipBehavior, defaultValue: null)); } diff --git a/packages/flutter/test/material/bottom_sheet_theme_test.dart b/packages/flutter/test/material/bottom_sheet_theme_test.dart index bcd7f38b38..893b8edecc 100644 --- a/packages/flutter/test/material/bottom_sheet_theme_test.dart +++ b/packages/flutter/test/material/bottom_sheet_theme_test.dart @@ -70,7 +70,7 @@ void main() { find.descendant( of: find.byType(BottomSheet), matching: find.byType(Material), - ).first, + ), ); expect(material.color, null); expect(material.elevation, 0.0); @@ -97,7 +97,7 @@ void main() { find.descendant( of: find.byType(BottomSheet), matching: find.byType(Material), - ).first, + ), ); expect(material.color, bottomSheetTheme.backgroundColor); expect(material.elevation, bottomSheetTheme.elevation); @@ -133,13 +133,120 @@ void main() { find.descendant( of: find.byType(BottomSheet), matching: find.byType(Material), - ).first, + ), ); expect(material.color, backgroundColor); expect(material.elevation, elevation); expect(material.shape, shape); expect(material.clipBehavior, clipBehavior); }); + + testWidgets('BottomSheetThemeData.modalElevation takes priority over BottomSheetThemeData.elevation for modal bottom sheets', (WidgetTester tester) async { + const double modalElevation = 5.0; + const double persistentElevation = 7.0; + const BottomSheetThemeData bottomSheetTheme = BottomSheetThemeData( + elevation: persistentElevation, + modalElevation: modalElevation, + ); + + await tester.pumpWidget(bottomSheetWithElevations(bottomSheetTheme)); + await tester.tap(find.text('Show Modal')); + await tester.pumpAndSettle(); + + final Material material = tester.widget( + find.descendant( + of: find.byType(BottomSheet), + matching: find.byType(Material), + ), + ); + expect(material.elevation, modalElevation); + }); + + testWidgets('BottomSheetThemeData.elevation takes priority over BottomSheetThemeData.modalElevation for peristent bottom sheets', (WidgetTester tester) async { + const double modalElevation = 5.0; + const double persistentElevation = 7.0; + const BottomSheetThemeData bottomSheetTheme = BottomSheetThemeData( + elevation: persistentElevation, + modalElevation: modalElevation, + ); + + await tester.pumpWidget(bottomSheetWithElevations(bottomSheetTheme)); + await tester.tap(find.text('Show Persistent')); + await tester.pumpAndSettle(); + + final Material material = tester.widget( + find.descendant( + of: find.byType(BottomSheet), + matching: find.byType(Material), + ), + ); + expect(material.elevation, persistentElevation); + }); + + testWidgets('BottomSheetThemeData.modalElevation doesn\'t apply to persistent bottom sheets', (WidgetTester tester) async { + const double modalElevation = 5.0; + const BottomSheetThemeData bottomSheetTheme = BottomSheetThemeData( + modalElevation: modalElevation, + ); + + await tester.pumpWidget(bottomSheetWithElevations(bottomSheetTheme)); + await tester.tap(find.text('Show Persistent')); + await tester.pumpAndSettle(); + + final Material material = tester.widget( + find.descendant( + of: find.byType(BottomSheet), + matching: find.byType(Material), + ), + ); + expect(material.elevation, 0); + }); +} + +Widget bottomSheetWithElevations(BottomSheetThemeData bottomSheetTheme) { + return MaterialApp( + theme: ThemeData(bottomSheetTheme: bottomSheetTheme), + home: Scaffold( + body: Builder( + builder: (BuildContext context) { + return Column( + children: [ + RawMaterialButton( + child: const Text('Show Modal'), + onPressed: () { + showModalBottomSheet( + context: context, + builder: (BuildContext _) { + return Container( + child: const Text( + 'This is a modal bottom sheet.', + ), + ); + }, + ); + }, + ), + RawMaterialButton( + child: const Text('Show Persistent'), + onPressed: () { + showBottomSheet( + context: context, + builder: (BuildContext _) { + return Container( + child: const Text( + 'This is a persistent bottom sheet.', + ), + ); + }, + ); + }, + ), + ], + ); + }, + ), + ), + ); } BottomSheetThemeData _bottomSheetTheme() {