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
3a93061e
Unverified
Commit
3a93061e
authored
7 years ago
by
Hans Muller
Committed by
GitHub
7 years ago
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Extended Floating Action Button (#15841)
parent
1f5d9041
No related merge requests found
Changes
4
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
307 additions
and
116 deletions
+307
-116
tabs_fab_demo.dart
...ples/flutter_gallery/lib/demo/material/tabs_fab_demo.dart
+37
-8
floating_action_button.dart
...ages/flutter/lib/src/material/floating_action_button.dart
+114
-43
scaffold.dart
packages/flutter/lib/src/material/scaffold.dart
+105
-63
floating_action_button_test.dart
...es/flutter/test/material/floating_action_button_test.dart
+51
-2
No files found.
examples/flutter_gallery/lib/demo/material/tabs_fab_demo.dart
View file @
3a93061e
...
...
@@ -44,6 +44,7 @@ class _TabsFabDemoState extends State<TabsFabDemo> with SingleTickerProviderStat
TabController
_controller
;
_Page
_selectedPage
;
bool
_extendedButtons
;
@override
void
initState
()
{
...
...
@@ -101,6 +102,30 @@ class _TabsFabDemoState extends State<TabsFabDemo> with SingleTickerProviderStat
);
}
Widget
buildFloatingActionButton
(
_Page
page
)
{
if
(!
page
.
fabDefined
)
return
null
;
if
(
_extendedButtons
)
{
return
new
FloatingActionButton
.
extended
(
key:
new
ValueKey
<
Key
>(
page
.
fabKey
),
tooltip:
'Show explanation'
,
backgroundColor:
page
.
fabColor
,
icon:
page
.
fabIcon
,
label:
new
Text
(
page
.
label
.
toUpperCase
()),
onPressed:
_showExplanatoryText
);
}
return
new
FloatingActionButton
(
key:
page
.
fabKey
,
tooltip:
'Show explanation'
,
backgroundColor:
page
.
fabColor
,
child:
page
.
fabIcon
,
onPressed:
_showExplanatoryText
);
}
@override
Widget
build
(
BuildContext
context
)
{
return
new
Scaffold
(
...
...
@@ -110,15 +135,19 @@ class _TabsFabDemoState extends State<TabsFabDemo> with SingleTickerProviderStat
bottom:
new
TabBar
(
controller:
_controller
,
tabs:
_allPages
.
map
((
_Page
page
)
=>
new
Tab
(
text:
page
.
label
.
toUpperCase
())).
toList
(),
)
),
floatingActionButton:
!
_selectedPage
.
fabDefined
?
null
:
new
FloatingActionButton
(
key:
_selectedPage
.
fabKey
,
tooltip:
'Show explanation'
,
backgroundColor:
_selectedPage
.
fabColor
,
child:
_selectedPage
.
fabIcon
,
onPressed:
_showExplanatoryText
),
actions:
<
Widget
>[
new
IconButton
(
icon:
const
Icon
(
Icons
.
sentiment_very_satisfied
),
onPressed:
()
{
setState
(()
{
_extendedButtons
=
!
_extendedButtons
;
});
},
),
],
),
floatingActionButton:
buildFloatingActionButton
(
_selectedPage
),
body:
new
TabBarView
(
controller:
_controller
,
children:
_allPages
.
map
(
buildTabView
).
toList
()
...
...
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/material/floating_action_button.dart
View file @
3a93061e
...
...
@@ -5,19 +5,28 @@
import
'dart:math'
as
math
;
import
'package:flutter/foundation.dart'
;
import
'package:flutter/painting.dart'
;
import
'package:flutter/widgets.dart'
;
import
'colors.dart'
;
import
'ink_well.dart'
;
import
'material.dart'
;
import
'button.dart'
;
import
'scaffold.dart'
;
import
'theme.dart'
;
import
'tooltip.dart'
;
// TODO(eseidel): This needs to change based on device size?
// http://material.google.com/layout/metrics-keylines.html#metrics-keylines-keylines-spacing
const
double
_kSize
=
56.0
;
const
double
_kSizeMini
=
40.0
;
const
BoxConstraints
_kSizeConstraints
=
const
BoxConstraints
.
tightFor
(
width:
56.0
,
height:
56.0
,
);
const
BoxConstraints
_kMiniSizeConstraints
=
const
BoxConstraints
.
tightFor
(
width:
40.0
,
height:
40.0
,
);
const
BoxConstraints
_kExtendedSizeConstraints
=
const
BoxConstraints
(
minHeight:
48.0
,
maxHeight:
48.0
,
);
class
_DefaultHeroTag
{
const
_DefaultHeroTag
();
...
...
@@ -52,13 +61,15 @@ class _DefaultHeroTag {
/// * [FlatButton]
/// * <https://material.google.com/components/buttons-floating-action-button.html>
class
FloatingActionButton
extends
StatefulWidget
{
/// Creates a floating action button.
/// Creates a
circular
floating action button.
///
/// Most commonly used in the [Scaffold.floatingActionButton] field.
/// The [elevation], [highlightElevation], [mini], [notchMargin], and [shape]
/// arguments must not be null.
const
FloatingActionButton
({
Key
key
,
this
.
child
,
this
.
tooltip
,
this
.
foregroundColor
,
this
.
backgroundColor
,
this
.
heroTag
:
const
_DefaultHeroTag
(),
this
.
elevation
:
6.0
,
...
...
@@ -66,7 +77,54 @@ class FloatingActionButton extends StatefulWidget {
@required
this
.
onPressed
,
this
.
mini
:
false
,
this
.
notchMargin
:
4.0
,
})
:
super
(
key:
key
);
this
.
shape
:
const
CircleBorder
(),
this
.
isExtended
:
false
,
})
:
assert
(
elevation
!=
null
),
assert
(
highlightElevation
!=
null
),
assert
(
mini
!=
null
),
assert
(
notchMargin
!=
null
),
assert
(
shape
!=
null
),
assert
(
isExtended
!=
null
),
_sizeConstraints
=
mini
?
_kMiniSizeConstraints
:
_kSizeConstraints
,
super
(
key:
key
);
/// Creates a wider [StadiumBorder] shaped floating action button with both
/// an [icon] and a [label].
///
/// The [label], [icon], [elevation], [highlightElevation]
/// [notchMargin], and [shape] arguments must not be null.
FloatingActionButton
.
extended
({
Key
key
,
this
.
tooltip
,
this
.
foregroundColor
,
this
.
backgroundColor
,
this
.
heroTag
:
const
_DefaultHeroTag
(),
this
.
elevation
:
6.0
,
this
.
highlightElevation
:
12.0
,
@required
this
.
onPressed
,
this
.
notchMargin
:
4.0
,
this
.
shape
:
const
StadiumBorder
(),
this
.
isExtended
:
true
,
@required
Widget
icon
,
@required
Widget
label
,
})
:
assert
(
elevation
!=
null
),
assert
(
highlightElevation
!=
null
),
assert
(
notchMargin
!=
null
),
assert
(
shape
!=
null
),
assert
(
isExtended
!=
null
),
_sizeConstraints
=
_kExtendedSizeConstraints
,
mini
=
false
,
child
=
new
Row
(
mainAxisSize:
MainAxisSize
.
min
,
children:
<
Widget
>[
const
SizedBox
(
width:
16.0
),
icon
,
const
SizedBox
(
width:
8.0
),
label
,
const
SizedBox
(
width:
20.0
),
],
),
super
(
key:
key
);
/// The widget below this widget in the tree.
///
...
...
@@ -79,9 +137,14 @@ class FloatingActionButton extends StatefulWidget {
/// used for accessibility.
final
String
tooltip
;
/// The default icon and text color.
///
/// Defaults to [ThemeData.accentIconTheme.color] for the current theme.
final
Color
foregroundColor
;
/// The color to use when filling the button.
///
/// Defaults to
the accent color of
the current theme.
/// Defaults to
[ThemeData.accentColor] for
the current theme.
final
Color
backgroundColor
;
/// The tag to apply to the button's [Hero] widget.
...
...
@@ -141,13 +204,32 @@ class FloatingActionButton extends StatefulWidget {
/// floating action button.
final
double
notchMargin
;
/// The shape of the button's [Material].
///
/// The button's highlight and splash are clipped to this shape. If the
/// button has an elevation, then its drop shadow is defined by this
/// shape as well.
final
ShapeBorder
shape
;
/// True if this is an "extended" floating action button.
///
/// Typically [extended] buttons have a [StadiumBorder] [shape]
/// and have been created with the [FloatingActionButton.extended]
/// constructor.
///
/// The [Scaffold] animates the appearance of ordinary floating
/// action buttons with scale and rotation transitions. Extended
/// floating action buttons are scaled and faded in.
final
bool
isExtended
;
final
BoxConstraints
_sizeConstraints
;
@override
_FloatingActionButtonState
createState
()
=>
new
_FloatingActionButtonState
();
}
class
_FloatingActionButtonState
extends
State
<
FloatingActionButton
>
{
bool
_highlight
=
false
;
VoidCallback
_clearComputeNotch
;
void
_handleHighlightChanged
(
bool
value
)
{
...
...
@@ -158,25 +240,33 @@ class _FloatingActionButtonState extends State<FloatingActionButton> {
@override
Widget
build
(
BuildContext
context
)
{
Color
iconColor
=
Colors
.
white
;
Color
materialColor
=
widget
.
backgroundColor
;
if
(
materialColor
==
null
)
{
final
ThemeData
themeData
=
Theme
.
of
(
context
);
materialColor
=
themeData
.
accentColor
;
iconColor
=
themeData
.
accentIconTheme
.
color
;
}
final
ThemeData
theme
=
Theme
.
of
(
context
);
final
Color
foregroundColor
=
widget
.
foregroundColor
??
theme
.
accentIconTheme
.
color
;
Widget
result
;
if
(
widget
.
child
!=
null
)
{
result
=
new
Center
(
child:
IconTheme
.
merge
(
data:
new
IconThemeData
(
color:
iconColor
),
child:
widget
.
child
,
result
=
IconTheme
.
merge
(
data:
new
IconThemeData
(
color:
foregroundColor
,
),
child:
widget
.
child
,
);
}
result
=
new
RawMaterialButton
(
onPressed:
widget
.
onPressed
,
onHighlightChanged:
_handleHighlightChanged
,
elevation:
_highlight
?
widget
.
highlightElevation
:
widget
.
elevation
,
constraints:
widget
.
_sizeConstraints
,
fillColor:
widget
.
backgroundColor
??
theme
.
accentColor
,
textStyle:
theme
.
accentTextTheme
.
button
.
copyWith
(
color:
foregroundColor
,
letterSpacing:
1.2
,
),
shape:
widget
.
shape
,
child:
result
,
);
if
(
widget
.
tooltip
!=
null
)
{
result
=
new
Tooltip
(
message:
widget
.
tooltip
,
...
...
@@ -184,25 +274,6 @@ class _FloatingActionButtonState extends State<FloatingActionButton> {
);
}
result
=
new
Material
(
color:
materialColor
,
type:
MaterialType
.
circle
,
elevation:
_highlight
?
widget
.
highlightElevation
:
widget
.
elevation
,
child:
new
Container
(
width:
widget
.
mini
?
_kSizeMini
:
_kSize
,
height:
widget
.
mini
?
_kSizeMini
:
_kSize
,
child:
new
Semantics
(
button:
true
,
enabled:
widget
.
onPressed
!=
null
,
child:
new
InkWell
(
onTap:
widget
.
onPressed
,
onHighlightChanged:
_handleHighlightChanged
,
child:
result
,
),
),
),
);
if
(
widget
.
heroTag
!=
null
)
{
result
=
new
Hero
(
tag:
widget
.
heroTag
,
...
...
This diff is collapsed.
Click to expand it.
packages/flutter/lib/src/material/scaffold.dart
View file @
3a93061e
This diff is collapsed.
Click to expand it.
packages/flutter/test/material/floating_action_button_test.dart
View file @
3a93061e
...
...
@@ -65,10 +65,59 @@ void main() {
expect
(
find
.
byType
(
Text
),
findsNothing
);
await
tester
.
longPress
(
find
.
byType
(
FloatingActionButton
));
await
tester
.
pump
();
await
tester
.
pump
AndSettle
();
expect
(
find
.
byType
(
Text
),
findsOneWidget
);
});
testWidgets
(
'FloatingActionButton.isExtended'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
const
Scaffold
(
floatingActionButton:
const
FloatingActionButton
(
onPressed:
null
),
),
),
);
final
Finder
fabFinder
=
find
.
byType
(
FloatingActionButton
);
FloatingActionButton
getFabWidget
()
{
return
tester
.
widget
<
FloatingActionButton
>(
fabFinder
);
}
expect
(
getFabWidget
().
isExtended
,
false
);
expect
(
getFabWidget
().
shape
,
const
CircleBorder
());
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
new
Scaffold
(
floatingActionButton:
new
FloatingActionButton
.
extended
(
label:
const
Text
(
'label'
),
icon:
const
Icon
(
Icons
.
android
),
onPressed:
null
,
),
),
),
);
expect
(
getFabWidget
().
isExtended
,
true
);
expect
(
getFabWidget
().
shape
,
const
StadiumBorder
());
expect
(
find
.
text
(
'label'
),
findsOneWidget
);
expect
(
find
.
byType
(
Icon
),
findsOneWidget
);
// Verify that the widget's height is 48 and that its internal
/// horizontal layout is: 16 icon 8 label 20
expect
(
tester
.
getSize
(
fabFinder
).
height
,
48.0
);
final
double
fabLeft
=
tester
.
getTopLeft
(
fabFinder
).
dx
;
final
double
fabRight
=
tester
.
getTopRight
(
fabFinder
).
dx
;
final
double
iconLeft
=
tester
.
getTopLeft
(
find
.
byType
(
Icon
)).
dx
;
final
double
iconRight
=
tester
.
getTopRight
(
find
.
byType
(
Icon
)).
dx
;
final
double
labelLeft
=
tester
.
getTopLeft
(
find
.
text
(
'label'
)).
dx
;
final
double
labelRight
=
tester
.
getTopRight
(
find
.
text
(
'label'
)).
dx
;
expect
(
iconLeft
-
fabLeft
,
16.0
);
expect
(
labelLeft
-
iconRight
,
8.0
);
expect
(
fabRight
-
labelRight
,
20.0
);
});
testWidgets
(
'Floating Action Button heroTag'
,
(
WidgetTester
tester
)
async
{
BuildContext
theContext
;
await
tester
.
pumpWidget
(
...
...
@@ -372,7 +421,7 @@ class GeometryListenerState extends State<GeometryListener> {
final
ValueListenable
<
ScaffoldGeometry
>
newListenable
=
Scaffold
.
geometryOf
(
context
);
if
(
geometryListenable
==
newListenable
)
return
;
geometryListenable
=
newListenable
;
cache
=
new
GeometryCachePainter
(
geometryListenable
);
}
...
...
This diff is collapsed.
Click to expand it.
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