Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/flutter/lib/material.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ export 'src/material/bottom_app_bar.dart';
export 'src/material/bottom_app_bar_theme.dart';
export 'src/material/bottom_navigation_bar.dart';
export 'src/material/bottom_sheet.dart';
export 'src/material/bottom_sheet_theme.dart';
export 'src/material/button.dart';
export 'src/material/button_bar.dart';
export 'src/material/button_theme.dart';
Expand Down
68 changes: 56 additions & 12 deletions packages/flutter/lib/src/material/bottom_sheet.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/scheduler.dart';
import 'package:flutter/widgets.dart';

import 'bottom_sheet_theme.dart';
import 'colors.dart';
import 'debug.dart';
import 'material.dart';
Expand Down Expand Up @@ -56,14 +57,15 @@ class BottomSheet extends StatefulWidget {
Key key,
this.animationController,
this.enableDrag = true,
this.elevation = 0.0,
this.backgroundColor,
this.elevation,
this.shape,
@required this.onClosing,
@required this.builder,
}) : assert(enableDrag != null),
assert(onClosing != null),
assert(builder != null),
assert(elevation != null && elevation >= 0.0),
assert(elevation == null || elevation >= 0.0),
super(key: key);

/// The animation controller that controls the bottom sheet's entrance and
Expand Down Expand Up @@ -92,17 +94,26 @@ class BottomSheet extends StatefulWidget {
/// Default is true.
final bool enableDrag;

/// The bottom sheet's background color.
///
/// Defines the bottom sheet's [Material.color].
///
/// Defaults to null and falls back to [Material]'s default.
final Color backgroundColor;

/// The z-coordinate at which to place this material relative to its parent.
///
/// This controls the size of the shadow below the material.
///
/// Defaults to 0. The value is non-negative.
final double elevation;

/// The color for the [Material] of the bottom sheet.
/// The shape of the bottom sheet.
///
/// Defaults to [Colors.white]. The value must not be null.
final Color backgroundColor;
/// Defines the bottom sheet's [Material.shape].
///
/// Defaults to null and falls back to [Material]'s default.
final ShapeBorder shape;

@override
_BottomSheetState createState() => _BottomSheetState();
Expand Down Expand Up @@ -170,10 +181,16 @@ class _BottomSheetState extends State<BottomSheet> {

@override
Widget build(BuildContext context) {
final BottomSheetThemeData bottomSheetTheme = Theme.of(context).bottomSheetTheme;
final Color color = widget.backgroundColor ?? bottomSheetTheme.backgroundColor;
final double elevation = widget.elevation ?? bottomSheetTheme.elevation ?? 0;
final ShapeBorder shape = widget.shape ?? bottomSheetTheme.shape;

final Widget bottomSheet = Material(
key: _childKey,
color: widget.backgroundColor,
elevation: widget.elevation,
color: color,
elevation: elevation,
shape: shape,
child: NotificationListener<DraggableScrollableNotification>(
onNotification: extentChanged,
child: widget.builder(context),
Expand Down Expand Up @@ -227,12 +244,18 @@ class _ModalBottomSheet<T> extends StatefulWidget {
const _ModalBottomSheet({
Key key,
this.route,
this.backgroundColor,
this.elevation,
this.shape,
this.isScrollControlled = false,
}) : assert(isScrollControlled != null),
super(key: key);

final _ModalBottomSheetRoute<T> route;
final bool isScrollControlled;
final Color backgroundColor;
final double elevation;
final ShapeBorder shape;

@override
_ModalBottomSheetState<T> createState() => _ModalBottomSheetState<T>();
Expand Down Expand Up @@ -279,14 +302,16 @@ class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
child: CustomSingleChildLayout(
delegate: _ModalBottomSheetLayout(animationValue, widget.isScrollControlled),
child: BottomSheet(
backgroundColor: widget.route.backgroundColor,
animationController: widget.route._animationController,
onClosing: () {
if (widget.route.isCurrent) {
Navigator.pop(context);
}
},
builder: widget.route.builder,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
shape: widget.shape,
),
),
),
Expand All @@ -302,8 +327,10 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
this.builder,
this.theme,
this.barrierLabel,
@required this.isScrollControlled,
this.backgroundColor,
this.elevation,
this.shape,
@required this.isScrollControlled,
RouteSettings settings,
}) : assert(isScrollControlled != null),
super(settings: settings);
Expand All @@ -312,6 +339,8 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
final ThemeData theme;
final bool isScrollControlled;
final Color backgroundColor;
final double elevation;
final ShapeBorder shape;

@override
Duration get transitionDuration => _bottomSheetDuration;
Expand All @@ -327,6 +356,7 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {

AnimationController _animationController;


@override
AnimationController createAnimationController() {
assert(_animationController == null);
Expand All @@ -341,7 +371,13 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
Widget bottomSheet = MediaQuery.removePadding(
context: context,
removeTop: true,
child: _ModalBottomSheet<T>(route: this, isScrollControlled: isScrollControlled),
child: _ModalBottomSheet<T>(
route: this,
backgroundColor: backgroundColor,
elevation: elevation,
shape: shape,
isScrollControlled: isScrollControlled
),
);
if (theme != null)
bottomSheet = Theme(data: theme, child: bottomSheet);
Expand Down Expand Up @@ -384,8 +420,10 @@ class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
Future<T> showModalBottomSheet<T>({
@required BuildContext context,
@required WidgetBuilder builder,
bool isScrollControlled = false,
Color backgroundColor,
double elevation,
ShapeBorder shape,
bool isScrollControlled = false,
}) {
assert(context != null);
assert(builder != null);
Expand All @@ -397,8 +435,10 @@ Future<T> showModalBottomSheet<T>({
builder: builder,
theme: Theme.of(context, shadowThemeOnly: true),
isScrollControlled: isScrollControlled,
backgroundColor: backgroundColor,
barrierLabel: MaterialLocalizations.of(context).modalBarrierDismissLabel,
backgroundColor: backgroundColor,
elevation: elevation,
shape: shape,
));
}

Expand Down Expand Up @@ -440,6 +480,8 @@ PersistentBottomSheetController<T> showBottomSheet<T>({
@required BuildContext context,
@required WidgetBuilder builder,
Color backgroundColor,
double elevation,
ShapeBorder shape,
}) {
assert(context != null);
assert(builder != null);
Expand All @@ -448,5 +490,7 @@ PersistentBottomSheetController<T> showBottomSheet<T>({
return Scaffold.of(context).showBottomSheet<T>(
builder,
backgroundColor: backgroundColor,
elevation: elevation,
shape: shape,
);
}
111 changes: 111 additions & 0 deletions packages/flutter/lib/src/material/bottom_sheet_theme.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:ui' show lerpDouble;

import 'package:flutter/foundation.dart';
import 'package:flutter/rendering.dart';

/// Defines default property values for [BottomSheet]'s [Material].
///
/// Descendant widgets obtain the current [BottomSheetThemeData] object
/// using `Theme.of(context).bottomSheetTheme`. Instances of
/// [BottomSheetThemeData] can be customized with
/// [BottomSheetThemeData.copyWith].
///
/// Typically a [BottomSheetThemeData] is specified as part of the
/// overall [Theme] with [ThemeData.bottomSheetTheme].
///
/// All [BottomSheetThemeData] properties are `null` by default.
/// When null, the [BottomSheet] will provide its own defaults.
///
/// See also:
///
/// * [ThemeData], which describes the overall theme information for the
/// application.
class BottomSheetThemeData extends Diagnosticable {
/// Creates a theme that can be used for [ThemeData.bottomSheetTheme].
const BottomSheetThemeData({
this.backgroundColor,
this.elevation,
this.shape,
});

/// Default value for [BottomSheet.backgroundColor].
///
/// If null, [BottomSheet] defaults to [Material]'s default.
final Color backgroundColor;

/// Default value for [BottomSheet.elevation].
///
/// {@macro flutter.material.material.elevation}
///
/// If null, [BottomSheet] defaults to 0.0.
final double elevation;

/// Default value for [BottomSheet.shape].
///
/// If null, no overriding shape is specified for [BottomSheet], so the
/// [BottomSheet] is rectangular.
final ShapeBorder shape;

/// Creates a copy of this object with the given fields replaced with the
/// new values.
BottomSheetThemeData copyWith({
Color backgroundColor,
double elevation,
ShapeBorder shape,
}) {
return BottomSheetThemeData(
backgroundColor: backgroundColor ?? this.backgroundColor,
elevation: elevation ?? this.elevation,
shape: shape ?? this.shape,
);
}

/// Linearly interpolate between two bottom sheet themes.
///
/// If both arguments are null then null is returned.
///
/// {@macro dart.ui.shadow.lerp}
static BottomSheetThemeData lerp(BottomSheetThemeData a, BottomSheetThemeData b, double t) {
assert(t != null);
if (a == null && b == null)
return null;
return BottomSheetThemeData(
backgroundColor: Color.lerp(a?.backgroundColor, b?.backgroundColor, t),
elevation: lerpDouble(a?.elevation, b?.elevation, t),
shape: ShapeBorder.lerp(a?.shape, b?.shape, t),
);
}

@override
int get hashCode {
return hashValues(
backgroundColor,
elevation,
shape,
);
}

@override
bool operator ==(Object other) {
if (identical(this, other))
return true;
if (other.runtimeType != runtimeType)
return false;
final BottomSheetThemeData typedOther = other;
return typedOther.backgroundColor == backgroundColor
&& typedOther.elevation == elevation
&& typedOther.shape == shape;
}

@override
void debugFillProperties(DiagnosticPropertiesBuilder properties) {
super.debugFillProperties(properties);
properties.add(DiagnosticsProperty<Color>('backgroundColor', backgroundColor, defaultValue: null));
properties.add(DiagnosticsProperty<double>('elevation', elevation, defaultValue: null));
properties.add(DiagnosticsProperty<ShapeBorder>('shape', shape, defaultValue: null));
}
}
14 changes: 14 additions & 0 deletions packages/flutter/lib/src/material/scaffold.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1541,6 +1541,8 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
bool isPersistent, {
AnimationController animationController,
Color backgroundColor,
double elevation,
ShapeBorder shape,
}) {
assert(() {
if (widget.bottomSheet != null && isPersistent && _currentBottomSheet != null) {
Expand Down Expand Up @@ -1619,6 +1621,8 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
builder: builder,
isPersistent: isPersistent,
backgroundColor: backgroundColor,
elevation: elevation,
shape: shape,
);

if (!isPersistent)
Expand Down Expand Up @@ -1673,6 +1677,8 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
PersistentBottomSheetController<T> showBottomSheet<T>(
WidgetBuilder builder, {
Color backgroundColor,
double elevation,
ShapeBorder shape,
}) {
assert(() {
if (widget.bottomSheet != null) {
Expand All @@ -1694,6 +1700,8 @@ class ScaffoldState extends State<Scaffold> with TickerProviderStateMixin {
false,
animationController: controller,
backgroundColor: backgroundColor,
elevation: elevation,
shape: shape,
);
});
return _currentBottomSheet;
Expand Down Expand Up @@ -2216,6 +2224,8 @@ class _StandardBottomSheet extends StatefulWidget {
this.builder,
this.isPersistent = false,
this.backgroundColor,
this.elevation,
this.shape,
}) : super(key: key);

final AnimationController animationController; // we control it, but it must be disposed by whoever created it.
Expand All @@ -2225,6 +2235,8 @@ class _StandardBottomSheet extends StatefulWidget {
final WidgetBuilder builder;
final bool isPersistent;
final Color backgroundColor;
final double elevation;
final ShapeBorder shape;

@override
_StandardBottomSheetState createState() => _StandardBottomSheetState();
Expand Down Expand Up @@ -2311,6 +2323,8 @@ class _StandardBottomSheetState extends State<_StandardBottomSheet> {
onClosing: widget.onClosing,
builder: widget.builder,
backgroundColor: widget.backgroundColor,
elevation: widget.elevation,
shape: widget.shape,
),
),
);
Expand Down
Loading