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
4d80f3cb
Commit
4d80f3cb
authored
Sep 09, 2016
by
Hans Muller
Committed by
GitHub
Sep 09, 2016
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix app bar title overflow with centerTitle:true (#5773)
parent
5a802995
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
232 additions
and
39 deletions
+232
-39
app_bar.dart
packages/flutter/lib/src/material/app_bar.dart
+95
-39
app_bar_test.dart
packages/flutter/test/material/app_bar_test.dart
+137
-0
No files found.
packages/flutter/lib/src/material/app_bar.dart
View file @
4d80f3cb
...
...
@@ -24,6 +24,65 @@ abstract class AppBarBottomWidget extends Widget {
double
get
bottomHeight
;
}
enum
_ToolBarSlot
{
leading
,
title
,
actions
,
}
class
_ToolBarLayout
extends
MultiChildLayoutDelegate
{
_ToolBarLayout
({
this
.
centerTitle
});
// If false the title should be left or right justified within the space bewteen
// the leading and actions widgets, depending on the locale's writing direction.
// If true the title is centered within the toolbar (not within the horizontal
// space bewteen the leading and actions widgets).
final
bool
centerTitle
;
static
const
double
kLeadingWidth
=
24.0
;
static
const
double
kTitleLeft
=
64.0
;
// The AppBar pads left and right an additional 8.0.
@override
void
performLayout
(
Size
size
)
{
double
actionsWidth
=
0.0
;
if
(
hasChild
(
_ToolBarSlot
.
leading
))
{
final
BoxConstraints
constraints
=
new
BoxConstraints
.
tight
(
new
Size
(
kLeadingWidth
,
size
.
height
));
layoutChild
(
_ToolBarSlot
.
leading
,
constraints
);
positionChild
(
_ToolBarSlot
.
leading
,
Offset
.
zero
);
}
if
(
hasChild
(
_ToolBarSlot
.
actions
))
{
final
BoxConstraints
constraints
=
new
BoxConstraints
.
loose
(
size
);
actionsWidth
=
layoutChild
(
_ToolBarSlot
.
actions
,
constraints
).
width
;
positionChild
(
_ToolBarSlot
.
actions
,
new
Offset
(
size
.
width
-
actionsWidth
,
0.0
));
}
if
(
hasChild
(
_ToolBarSlot
.
title
))
{
final
double
maxWidth
=
size
.
width
-
kTitleLeft
-
actionsWidth
;
final
BoxConstraints
constraints
=
new
BoxConstraints
.
loose
(
size
).
copyWith
(
maxWidth:
maxWidth
);
final
Size
titleSize
=
layoutChild
(
_ToolBarSlot
.
title
,
constraints
);
final
double
titleY
=
(
size
.
height
-
titleSize
.
height
)
/
2.0
;
double
titleX
=
kTitleLeft
;
// If the centered title will not fit between the leading and actions
// widgets, then align its left or right edge with the adjacent boundary.
if
(
centerTitle
)
{
titleX
=
(
size
.
width
-
titleSize
.
width
)
/
2.0
;
if
(
titleX
+
titleSize
.
width
>
size
.
width
-
actionsWidth
)
titleX
=
size
.
width
-
actionsWidth
-
titleSize
.
width
;
else
if
(
titleX
<
kTitleLeft
)
titleX
=
kTitleLeft
;
}
positionChild
(
_ToolBarSlot
.
title
,
new
Offset
(
titleX
,
titleY
));
}
}
@override
bool
shouldRelayout
(
_ToolBarLayout
oldDelegate
)
=>
centerTitle
!=
oldDelegate
.
centerTitle
;
}
// TODO(eseidel) Toolbar needs to change size based on orientation:
// http://www.google.com/design/spec/layout/structure.html#structure-app-bar
// Mobile Landscape: 48dp
...
...
@@ -215,6 +274,7 @@ class AppBar extends StatelessWidget {
iconTheme:
iconTheme
??
this
.
iconTheme
,
textTheme:
textTheme
??
this
.
textTheme
,
padding:
padding
??
this
.
padding
,
centerTitle:
centerTitle
??
this
.
centerTitle
,
heroTag:
heroTag
??
this
.
heroTag
,
expandedHeight:
expandedHeight
??
this
.
_expandedHeight
,
collapsedHeight:
collapsedHeight
??
this
.
_collapsedHeight
...
...
@@ -272,8 +332,6 @@ class AppBar extends StatelessWidget {
TextStyle
centerStyle
=
textTheme
?.
title
??
themeData
.
primaryTextTheme
.
title
;
TextStyle
sideStyle
=
textTheme
?.
body1
??
themeData
.
primaryTextTheme
.
body1
;
final
bool
effectiveCenterTitle
=
_getEffectiveCenterTitle
(
themeData
);
Brightness
brightness
=
this
.
brightness
??
themeData
.
primaryColorBrightness
;
SystemChrome
.
setSystemUIOverlayStyle
(
brightness
==
Brightness
.
dark
?
mojom
.
SystemUiOverlayStyle
.
light
...
...
@@ -291,52 +349,50 @@ class AppBar extends StatelessWidget {
);
}
Widget
centerWidget
;
if
(
title
!=
null
)
{
centerWidget
=
new
DefaultTextStyle
(
style:
centerStyle
,
softWrap:
false
,
overflow:
TextOverflow
.
ellipsis
,
child:
title
final
List
<
Widget
>
toolBarChildren
=
<
Widget
>[]
;
if
(
leading
!=
null
)
{
toolBarChildren
.
add
(
new
LayoutId
(
id:
_ToolBarSlot
.
leading
,
child:
leading
)
);
}
final
List
<
Widget
>
toolBarRow
=
<
Widget
>[];
if
(
leading
!=
null
)
{
toolBarRow
.
add
(
new
Padding
(
padding:
new
EdgeInsets
.
only
(
right:
16.0
),
child:
leading
));
if
(
title
!=
null
)
{
toolBarChildren
.
add
(
new
LayoutId
(
id:
_ToolBarSlot
.
title
,
child:
new
DefaultTextStyle
(
style:
centerStyle
,
softWrap:
false
,
overflow:
TextOverflow
.
ellipsis
,
child:
title
)
)
);
}
toolBarRow
.
add
(
new
Flexible
(
child:
new
Align
(
// TODO(abarth): In RTL this should be aligned to the right.
alignment:
FractionalOffset
.
centerLeft
,
child:
new
Padding
(
padding:
new
EdgeInsets
.
only
(
left:
8.0
),
child:
effectiveCenterTitle
?
null
:
centerWidget
if
(
actions
!=
null
&&
actions
.
isNotEmpty
)
{
toolBarChildren
.
add
(
new
LayoutId
(
id:
_ToolBarSlot
.
actions
,
child:
new
Row
(
mainAxisSize:
MainAxisSize
.
min
,
children:
actions
)
)
)
));
if
(
actions
!=
null
)
toolBarRow
.
addAll
(
actions
);
);
}
Widget
toolBar
=
new
Padding
(
padding:
const
EdgeInsets
.
symmetric
(
horizontal:
8.0
),
child:
new
Row
(
children:
toolBarRow
)
child:
new
CustomMultiChildLayout
(
delegate:
new
_ToolBarLayout
(
centerTitle:
_getEffectiveCenterTitle
(
themeData
)
),
children:
toolBarChildren
)
);
if
(
effectiveCenterTitle
&&
centerWidget
!=
null
)
{
toolBar
=
new
Stack
(
children:
<
Widget
>[
// TODO(abarth): If there isn't enough room, we should move the title
// off center rather than overlap the actions.
new
Center
(
child:
centerWidget
),
toolBar
]
);
}
Widget
appBar
=
new
SizedBox
(
height:
kToolBarHeight
,
child:
new
IconTheme
.
merge
(
...
...
packages/flutter/test/material/app_bar_test.dart
View file @
4d80f3cb
...
...
@@ -42,4 +42,141 @@ void main() {
expect
(
center
.
x
,
greaterThan
(
400
-
size
.
width
/
2.0
));
expect
(
center
.
x
,
lessThan
(
400
+
size
.
width
/
2.0
));
});
testWidgets
(
'AppBar centerTitle:true centers on Android'
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
MaterialApp
(
theme:
new
ThemeData
(
platform:
TargetPlatform
.
android
),
home:
new
Scaffold
(
appBar:
new
AppBar
(
centerTitle:
true
,
title:
new
Text
(
'X'
)
)
)
)
);
Finder
title
=
find
.
text
(
'X'
);
Point
center
=
tester
.
getCenter
(
title
);
Size
size
=
tester
.
getSize
(
title
);
expect
(
center
.
x
,
greaterThan
(
400
-
size
.
width
/
2.0
));
expect
(
center
.
x
,
lessThan
(
400
+
size
.
width
/
2.0
));
});
testWidgets
(
'AppBar centerTitle:false title left edge is 72.0 '
,
(
WidgetTester
tester
)
async
{
await
tester
.
pumpWidget
(
new
MaterialApp
(
home:
new
Scaffold
(
appBar:
new
AppBar
(
centerTitle:
false
,
title:
new
Text
(
'X'
)
)
)
)
);
expect
(
tester
.
getTopLeft
(
find
.
text
(
'X'
)).
x
,
72.0
);
});
testWidgets
(
'AppBar centerTitle:false title overflow OK '
,
(
WidgetTester
tester
)
async
{
// The app bar's title should be constrained to fit within the available space
// between the leading and actions widgets.
Key
titleKey
=
new
UniqueKey
();
Widget
leading
;
List
<
Widget
>
actions
;
Widget
buildApp
()
{
return
new
MaterialApp
(
home:
new
Scaffold
(
appBar:
new
AppBar
(
leading:
leading
,
centerTitle:
false
,
title:
new
Container
(
key:
titleKey
,
constraints:
new
BoxConstraints
.
loose
(
const
Size
(
1000.0
,
1000.0
))
),
actions:
actions
)
)
);
}
await
tester
.
pumpWidget
(
buildApp
());
Finder
title
=
find
.
byKey
(
titleKey
);
expect
(
tester
.
getTopLeft
(
title
).
x
,
72.0
);
// The toolbar's contents are padded on the right by 8.0
expect
(
tester
.
getSize
(
title
).
width
,
equals
(
800.0
-
72.0
-
8.0
));
actions
=
<
Widget
>[
new
SizedBox
(
width:
100.0
),
new
SizedBox
(
width:
100.0
)
];
await
tester
.
pumpWidget
(
buildApp
());
expect
(
tester
.
getTopLeft
(
title
).
x
,
72.0
);
// The title shrinks by 200.0 to allow for the actions widgets.
expect
(
tester
.
getSize
(
title
).
width
,
equals
(
800.0
-
72.0
-
8.0
-
200.0
));
leading
=
new
Container
();
// AppBar will constrain the width to 24.0
await
tester
.
pumpWidget
(
buildApp
());
expect
(
tester
.
getTopLeft
(
title
).
x
,
72.0
);
// Adding a leading widget shouldn't effect the title's size
expect
(
tester
.
getSize
(
title
).
width
,
equals
(
800.0
-
72.0
-
8.0
-
200.0
));
});
testWidgets
(
'AppBar centerTitle:true title overflow OK '
,
(
WidgetTester
tester
)
async
{
// The app bar's title should be constrained to fit within the available space
// between the leading and actions widgets. When it's also centered it may
// also be left or right justified if it doesn't fit in the overall center.
Key
titleKey
=
new
UniqueKey
();
double
titleWidth
=
700.0
;
Widget
leading
=
new
Container
();
List
<
Widget
>
actions
;
Widget
buildApp
()
{
return
new
MaterialApp
(
home:
new
Scaffold
(
appBar:
new
AppBar
(
leading:
leading
,
centerTitle:
true
,
title:
new
Container
(
key:
titleKey
,
constraints:
new
BoxConstraints
.
loose
(
new
Size
(
titleWidth
,
1000.0
))
),
actions:
actions
)
)
);
}
// Centering a title with width 700 within the 800 pixel wide test widget
// would mean that its left edge would have to be 50. The material spec says
// that the left edge of the title must be atleast 72.
await
tester
.
pumpWidget
(
buildApp
());
Finder
title
=
find
.
byKey
(
titleKey
);
expect
(
tester
.
getTopLeft
(
title
).
x
,
72.0
);
expect
(
tester
.
getSize
(
title
).
width
,
equals
(
700.0
));
// Centering a title with width 620 within the 800 pixel wide test widget
// would mean that its left edge would have to be 90. We reserve 72
// on the left and the padded actions occupy 90 + 8 on the right. That
// leaves 630, so the title is right justified but its width isn't changed.
await
tester
.
pumpWidget
(
buildApp
());
leading
=
null
;
titleWidth
=
620.0
;
actions
=
<
Widget
>[
new
SizedBox
(
width:
45.0
),
new
SizedBox
(
width:
45.0
)
];
await
tester
.
pumpWidget
(
buildApp
());
expect
(
tester
.
getTopLeft
(
title
).
x
,
800
-
620
-
45
-
45
-
8
);
expect
(
tester
.
getSize
(
title
).
width
,
equals
(
620.0
));
});
}
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