Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
57333748
Unverified
Commit
57333748
authored
Mar 04, 2022
by
Taha Tesser
Committed by
GitHub
Mar 04, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Migrate `Dialog` to Material 3 (#98919)
parent
671aa9e9
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
186 additions
and
17 deletions
+186
-17
gen_defaults.dart
dev/tools/gen_defaults/bin/gen_defaults.dart
+2
-0
dialog_template.dart
dev/tools/gen_defaults/lib/dialog_template.dart
+38
-0
dialog.dart
packages/flutter/lib/src/material/dialog.dart
+81
-10
theme_data.dart
packages/flutter/lib/src/material/theme_data.dart
+2
-0
dialog_test.dart
packages/flutter/test/material/dialog_test.dart
+63
-7
No files found.
dev/tools/gen_defaults/bin/gen_defaults.dart
View file @
57333748
...
...
@@ -17,6 +17,7 @@
import
'dart:convert'
;
import
'dart:io'
;
import
'package:gen_defaults/dialog_template.dart'
;
import
'package:gen_defaults/fab_template.dart'
;
import
'package:gen_defaults/navigation_bar_template.dart'
;
import
'package:gen_defaults/typography_template.dart'
;
...
...
@@ -67,4 +68,5 @@ Future<void> main(List<String> args) async {
FABTemplate
(
'
$materialLib
/floating_action_button.dart'
,
tokens
).
updateFile
();
NavigationBarTemplate
(
'
$materialLib
/navigation_bar.dart'
,
tokens
).
updateFile
();
TypographyTemplate
(
'
$materialLib
/typography.dart'
,
tokens
).
updateFile
();
DialogTemplate
(
'
$materialLib
/dialog.dart'
,
tokens
).
updateFile
();
}
dev/tools/gen_defaults/lib/dialog_template.dart
0 → 100644
View file @
57333748
// Copyright 2014 The Flutter 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
'template.dart'
;
class
DialogTemplate
extends
TokenTemplate
{
const
DialogTemplate
(
String
fileName
,
Map
<
String
,
dynamic
>
tokens
)
:
super
(
fileName
,
tokens
);
@override
String
generate
()
=>
'''
// Generated version
${tokens["version"]}
class _TokenDefaultsM3 extends DialogTheme {
_TokenDefaultsM3(this.context)
: _colors = Theme.of(context).colorScheme,
_textTheme = Theme.of(context).textTheme,
super(
alignment: Alignment.center,
elevation:
${elevation("md.comp.dialog.container")}
,
shape:
${shape("md.comp.dialog.container")}
,
);
final BuildContext context;
final ColorScheme _colors;
final TextTheme _textTheme;
// TODO(darrenaustin): overlay should be handled by Material widget: https://github.com/flutter/flutter/issues/9160
@override
Color? get backgroundColor => ElevationOverlay.colorWithOverlay(_colors.
${color("md.comp.dialog.container")}
, _colors.primary,
${elevation("md.comp.dialog.container")}
);
@override
TextStyle? get titleTextStyle => _textTheme.
${textStyle("md.comp.dialog.subhead")}
;
@override
TextStyle? get contentTextStyle => _textTheme.
${textStyle("md.comp.dialog.supporting-text")}
;
}
'''
;
}
packages/flutter/lib/src/material/dialog.dart
View file @
57333748
...
...
@@ -6,12 +6,15 @@ import 'dart:ui';
import
'package:flutter/widgets.dart'
;
import
'color_scheme.dart'
;
import
'colors.dart'
;
import
'debug.dart'
;
import
'dialog_theme.dart'
;
import
'elevation_overlay.dart'
;
import
'ink_well.dart'
;
import
'material.dart'
;
import
'material_localizations.dart'
;
import
'text_theme.dart'
;
import
'theme.dart'
;
import
'theme_data.dart'
;
...
...
@@ -128,13 +131,12 @@ class Dialog extends StatelessWidget {
/// {@macro flutter.widgets.ProxyWidget.child}
final
Widget
?
child
;
static
const
RoundedRectangleBorder
_defaultDialogShape
=
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4.0
)));
static
const
double
_defaultElevation
=
24.0
;
@override
Widget
build
(
BuildContext
context
)
{
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
DialogTheme
dialogTheme
=
DialogTheme
.
of
(
context
);
final
DialogTheme
defaults
=
theme
.
useMaterial3
?
_TokenDefaultsM3
(
context
)
:
_DefaultsM2
(
context
);
final
EdgeInsets
effectivePadding
=
MediaQuery
.
of
(
context
).
viewInsets
+
(
insetPadding
??
EdgeInsets
.
zero
);
return
AnimatedPadding
(
padding:
effectivePadding
,
...
...
@@ -147,13 +149,13 @@ class Dialog extends StatelessWidget {
removeBottom:
true
,
context:
context
,
child:
Align
(
alignment:
alignment
??
dialogTheme
.
alignment
??
Alignment
.
center
,
alignment:
alignment
??
dialogTheme
.
alignment
??
defaults
.
alignment
!
,
child:
ConstrainedBox
(
constraints:
const
BoxConstraints
(
minWidth:
280.0
),
child:
Material
(
color:
backgroundColor
??
dialogTheme
.
backgroundColor
??
Theme
.
of
(
context
).
dialogBackgroundColor
,
elevation:
elevation
??
dialogTheme
.
elevation
??
_defaultElevation
,
shape:
shape
??
dialogTheme
.
shape
??
_defaultDialogShape
,
elevation:
elevation
??
dialogTheme
.
elevation
??
defaults
.
elevation
!
,
shape:
shape
??
dialogTheme
.
shape
??
defaults
.
shape
!
,
type:
MaterialType
.
card
,
clipBehavior:
clipBehavior
,
child:
child
,
...
...
@@ -481,6 +483,7 @@ class AlertDialog extends StatelessWidget {
assert
(
debugCheckHasMaterialLocalizations
(
context
));
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
DialogTheme
dialogTheme
=
DialogTheme
.
of
(
context
);
final
DialogTheme
defaults
=
theme
.
useMaterial3
?
_TokenDefaultsM3
(
context
)
:
_DefaultsM2
(
context
);
String
?
label
=
semanticLabel
;
switch
(
theme
.
platform
)
{
...
...
@@ -498,6 +501,8 @@ class AlertDialog extends StatelessWidget {
// children.
final
double
paddingScaleFactor
=
_paddingScaleFactor
(
MediaQuery
.
of
(
context
).
textScaleFactor
);
final
TextDirection
?
textDirection
=
Directionality
.
maybeOf
(
context
);
const
double
m3ActionEndPadding
=
18.0
;
const
double
m3ActionBottomPadding
=
12.0
;
Widget
?
titleWidget
;
Widget
?
contentWidget
;
...
...
@@ -513,7 +518,7 @@ class AlertDialog extends StatelessWidget {
bottom:
effectiveTitlePadding
.
bottom
,
),
child:
DefaultTextStyle
(
style:
titleTextStyle
??
dialogTheme
.
titleTextStyle
??
theme
.
textTheme
.
headline6
!,
style:
titleTextStyle
??
dialogTheme
.
titleTextStyle
??
defaults
.
titleTextStyle
!,
child:
Semantics
(
// For iOS platform, the focus always lands on the title.
// Set nameRoute to false to avoid title being announce twice.
...
...
@@ -535,7 +540,7 @@ class AlertDialog extends StatelessWidget {
bottom:
effectiveContentPadding
.
bottom
,
),
child:
DefaultTextStyle
(
style:
contentTextStyle
??
dialogTheme
.
contentTextStyle
??
theme
.
textTheme
.
subtitle1
!,
style:
contentTextStyle
??
dialogTheme
.
contentTextStyle
??
defaults
.
contentTextStyle
!,
child:
Semantics
(
container:
true
,
child:
content
,
...
...
@@ -547,7 +552,13 @@ class AlertDialog extends StatelessWidget {
if
(
actions
!=
null
)
{
final
double
spacing
=
(
buttonPadding
?.
horizontal
??
16
)
/
2
;
actionsWidget
=
Padding
(
padding:
actionsPadding
.
add
(
EdgeInsets
.
all
(
spacing
)),
padding:
theme
.
useMaterial3
?
actionsPadding
.
add
(
EdgeInsets
.
all
(
spacing
))
.
add
(
const
EdgeInsets
.
only
(
right:
m3ActionEndPadding
,
bottom:
m3ActionBottomPadding
,
))
:
actionsPadding
.
add
(
EdgeInsets
.
all
(
spacing
)),
child:
OverflowBar
(
alignment:
actionsAlignment
??
MainAxisAlignment
.
end
,
spacing:
spacing
,
...
...
@@ -1145,3 +1156,63 @@ double _paddingScaleFactor(double textScaleFactor) {
// a non-scaled padding of 24 will produce a padding between 24 and 8.
return
lerpDouble
(
1.0
,
1.0
/
3.0
,
clampedTextScaleFactor
-
1.0
)!;
}
// Generate a DialogTheme that represents the M2 default values.
// This was generated by hand from the previous hand coded defaults
// for M2. It uses get method overrides instead of properties to
// avoid computing values that we may not need upfront.
class
_DefaultsM2
extends
DialogTheme
{
_DefaultsM2
(
this
.
context
)
:
_textTheme
=
Theme
.
of
(
context
).
textTheme
,
super
(
alignment:
Alignment
.
center
,
elevation:
24.0
,
shape:
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4.0
))),
);
final
BuildContext
context
;
final
TextTheme
_textTheme
;
@override
Color
?
get
backgroundColor
=>
Theme
.
of
(
context
).
dialogBackgroundColor
;
@override
TextStyle
?
get
titleTextStyle
=>
_textTheme
.
headline6
;
@override
TextStyle
?
get
contentTextStyle
=>
_textTheme
.
subtitle1
;
}
// BEGIN GENERATED TOKEN PROPERTIES
// Generated code to the end of this file. Do not edit by hand.
// These defaults are generated from the Material Design Token
// database by the script dev/tools/gen_defaults/bin/gen_defaults.dart.
// Generated version v0_86
class
_TokenDefaultsM3
extends
DialogTheme
{
_TokenDefaultsM3
(
this
.
context
)
:
_colors
=
Theme
.
of
(
context
).
colorScheme
,
_textTheme
=
Theme
.
of
(
context
).
textTheme
,
super
(
alignment:
Alignment
.
center
,
elevation:
6.0
,
shape:
const
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
only
(
topLeft:
Radius
.
circular
(
28.0
),
topRight:
Radius
.
circular
(
28.0
),
bottomLeft:
Radius
.
circular
(
28.0
),
bottomRight:
Radius
.
circular
(
28.0
))),
);
final
BuildContext
context
;
final
ColorScheme
_colors
;
final
TextTheme
_textTheme
;
// TODO(darrenaustin): overlay should be handled by Material widget: https://github.com/flutter/flutter/issues/9160
@override
Color
?
get
backgroundColor
=>
ElevationOverlay
.
colorWithOverlay
(
_colors
.
surface
,
_colors
.
primary
,
6.0
);
@override
TextStyle
?
get
titleTextStyle
=>
_textTheme
.
headlineSmall
;
@override
TextStyle
?
get
contentTextStyle
=>
_textTheme
.
bodyMedium
;
}
// END GENERATED TOKEN PROPERTIES
packages/flutter/lib/src/material/theme_data.dart
View file @
57333748
...
...
@@ -1157,6 +1157,8 @@ class ThemeData with Diagnosticable {
///
/// * [FloatingActionButton]
/// * [NavigationBar]
/// * [Dialog]
/// * [AlertDialog]
///
/// See also:
///
...
...
packages/flutter/test/material/dialog_test.dart
View file @
57333748
...
...
@@ -53,9 +53,14 @@ Finder _findButtonBar() {
return
find
.
ancestor
(
of:
find
.
byType
(
OverflowBar
),
matching:
find
.
byType
(
Padding
)).
first
;
}
const
ShapeBorder
_defaultDialogShape
=
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4.0
)));
const
ShapeBorder
_defaultM2DialogShape
=
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
all
(
Radius
.
circular
(
4.0
)));
final
ShapeBorder
_defaultM3DialogShape
=
RoundedRectangleBorder
(
borderRadius:
BorderRadius
.
circular
(
28.0
));
void
main
(
)
{
final
ThemeData
material3Theme
=
ThemeData
(
useMaterial3:
true
,
brightness:
Brightness
.
dark
);
final
ThemeData
material2Theme
=
ThemeData
(
useMaterial3:
false
,
brightness:
Brightness
.
dark
);
testWidgets
(
'Dialog is scrollable'
,
(
WidgetTester
tester
)
async
{
bool
didPressOk
=
false
;
final
AlertDialog
dialog
=
AlertDialog
(
...
...
@@ -104,20 +109,33 @@ void main() {
content:
Text
(
'Y'
),
actions:
<
Widget
>[
],
);
await
tester
.
pumpWidget
(
_buildAppWithDialog
(
dialog
,
theme:
ThemeData
(
brightness:
Brightness
.
dark
)
));
await
tester
.
pumpWidget
(
_buildAppWithDialog
(
dialog
,
theme:
material2Theme
));
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pumpAndSettle
();
final
Material
materialWidget
=
_getMaterialFromDialog
(
tester
);
expect
(
materialWidget
.
color
,
Colors
.
grey
[
800
]);
expect
(
materialWidget
.
shape
,
_defaultDialogShape
);
expect
(
materialWidget
.
shape
,
_default
M2
DialogShape
);
expect
(
materialWidget
.
elevation
,
24.0
);
final
Offset
bottomLeft
=
tester
.
getBottomLeft
(
find
.
descendant
(
of:
find
.
byType
(
Dialog
),
matching:
find
.
byType
(
Material
)),
);
expect
(
bottomLeft
.
dy
,
360.0
);
await
tester
.
tapAt
(
const
Offset
(
10.0
,
10.0
));
await
tester
.
pumpAndSettle
();
await
tester
.
pumpWidget
(
_buildAppWithDialog
(
dialog
,
theme:
material3Theme
));
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pumpAndSettle
();
final
Material
material3Widget
=
_getMaterialFromDialog
(
tester
);
expect
(
material3Widget
.
color
,
const
Color
(
0xff424242
));
expect
(
material3Widget
.
shape
,
_defaultM3DialogShape
);
expect
(
material3Widget
.
elevation
,
6.0
);
});
testWidgets
(
'Custom dialog elevation'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -223,7 +241,7 @@ void main() {
await
tester
.
pumpAndSettle
();
final
Material
materialWidget
=
_getMaterialFromDialog
(
tester
);
expect
(
materialWidget
.
shape
,
_defaultDialogShape
);
expect
(
materialWidget
.
shape
,
_default
M2
DialogShape
);
});
testWidgets
(
'Rectangular dialog shape'
,
(
WidgetTester
tester
)
async
{
...
...
@@ -585,9 +603,7 @@ void main() {
],
);
await
tester
.
pumpWidget
(
_buildAppWithDialog
(
dialog
),
);
await
tester
.
pumpWidget
(
_buildAppWithDialog
(
dialog
,
theme:
material2Theme
));
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pumpAndSettle
();
...
...
@@ -622,6 +638,46 @@ void main() {
tester
.
getBottomRight
(
find
.
byKey
(
key2
)).
dx
,
tester
.
getBottomRight
(
_findButtonBar
()).
dx
-
8.0
,
);
// right
// Dismiss it and test materail 3 dialog
await
tester
.
tapAt
(
const
Offset
(
10.0
,
10.0
));
await
tester
.
pumpAndSettle
();
await
tester
.
pumpWidget
(
_buildAppWithDialog
(
dialog
,
theme:
material3Theme
));
await
tester
.
tap
(
find
.
text
(
'X'
));
await
tester
.
pumpAndSettle
();
// Padding between both buttons
expect
(
tester
.
getBottomLeft
(
find
.
byKey
(
key2
)).
dx
,
tester
.
getBottomRight
(
find
.
byKey
(
key1
)).
dx
+
8.0
,
);
// Padding between button and edges of the button bar
// First button
expect
(
tester
.
getTopRight
(
find
.
byKey
(
key1
)).
dy
,
tester
.
getTopRight
(
_findButtonBar
()).
dy
+
8.0
,
);
// top
expect
(
tester
.
getBottomRight
(
find
.
byKey
(
key1
)).
dy
,
tester
.
getBottomRight
(
_findButtonBar
()).
dy
-
20.0
,
);
// bottom
// // Second button
expect
(
tester
.
getTopRight
(
find
.
byKey
(
key2
)).
dy
,
tester
.
getTopRight
(
_findButtonBar
()).
dy
+
8.0
,
);
// top
expect
(
tester
.
getBottomRight
(
find
.
byKey
(
key2
)).
dy
,
tester
.
getBottomRight
(
_findButtonBar
()).
dy
-
20.0
,
);
// bottom
expect
(
tester
.
getBottomRight
(
find
.
byKey
(
key2
)).
dx
,
tester
.
getBottomRight
(
_findButtonBar
()).
dx
-
26.0
,
);
// right
});
testWidgets
(
'AlertDialog.buttonPadding custom values'
,
(
WidgetTester
tester
)
async
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment