Make FlexibleSpaceBar title padding configurable (#27623)
This commit is contained in:
parent
bcd60fa89a
commit
022f7d892e
@ -47,6 +47,7 @@ class FlexibleSpaceBar extends StatefulWidget {
|
|||||||
this.title,
|
this.title,
|
||||||
this.background,
|
this.background,
|
||||||
this.centerTitle,
|
this.centerTitle,
|
||||||
|
this.titlePadding,
|
||||||
this.collapseMode = CollapseMode.parallax
|
this.collapseMode = CollapseMode.parallax
|
||||||
}) : assert(collapseMode != null),
|
}) : assert(collapseMode != null),
|
||||||
super(key: key);
|
super(key: key);
|
||||||
@ -63,7 +64,8 @@ class FlexibleSpaceBar extends StatefulWidget {
|
|||||||
|
|
||||||
/// Whether the title should be centered.
|
/// Whether the title should be centered.
|
||||||
///
|
///
|
||||||
/// Defaults to being adapted to the current [TargetPlatform].
|
/// By default this property is true if the current target platform
|
||||||
|
/// is [TargetPlatform.iOS], false otherwise.
|
||||||
final bool centerTitle;
|
final bool centerTitle;
|
||||||
|
|
||||||
/// Collapse effect while scrolling.
|
/// Collapse effect while scrolling.
|
||||||
@ -71,6 +73,18 @@ class FlexibleSpaceBar extends StatefulWidget {
|
|||||||
/// Defaults to [CollapseMode.parallax].
|
/// Defaults to [CollapseMode.parallax].
|
||||||
final CollapseMode collapseMode;
|
final CollapseMode collapseMode;
|
||||||
|
|
||||||
|
/// Defines how far the [title] is inset from either the widget's
|
||||||
|
/// bottom-left or its center.
|
||||||
|
///
|
||||||
|
/// Typically this property is used to adjust how far the title is
|
||||||
|
/// is inset from the bottom-left and it is specified along with
|
||||||
|
/// [centerTitle] false.
|
||||||
|
///
|
||||||
|
/// By default the value of this property is
|
||||||
|
/// `EdgeInsetsDirectional.only(start: 72, bottom: 16)` if the title is
|
||||||
|
/// not centered, `EdgeInsetsDirectional.only(start 0, bottom: 16)` otherwise.
|
||||||
|
final EdgeInsetsGeometry titlePadding;
|
||||||
|
|
||||||
/// Wraps a widget that contains an [AppBar] to convey sizing information down
|
/// Wraps a widget that contains an [AppBar] to convey sizing information down
|
||||||
/// to the [FlexibleSpaceBar].
|
/// to the [FlexibleSpaceBar].
|
||||||
///
|
///
|
||||||
@ -206,15 +220,17 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> {
|
|||||||
color: titleStyle.color.withOpacity(opacity)
|
color: titleStyle.color.withOpacity(opacity)
|
||||||
);
|
);
|
||||||
final bool effectiveCenterTitle = _getEffectiveCenterTitle(theme);
|
final bool effectiveCenterTitle = _getEffectiveCenterTitle(theme);
|
||||||
|
final EdgeInsetsGeometry padding = widget.titlePadding ??
|
||||||
|
EdgeInsetsDirectional.only(
|
||||||
|
start: effectiveCenterTitle ? 0.0 : 72.0,
|
||||||
|
bottom: 16.0
|
||||||
|
);
|
||||||
final double scaleValue = Tween<double>(begin: 1.5, end: 1.0).transform(t);
|
final double scaleValue = Tween<double>(begin: 1.5, end: 1.0).transform(t);
|
||||||
final Matrix4 scaleTransform = Matrix4.identity()
|
final Matrix4 scaleTransform = Matrix4.identity()
|
||||||
..scale(scaleValue, scaleValue, 1.0);
|
..scale(scaleValue, scaleValue, 1.0);
|
||||||
final Alignment titleAlignment = _getTitleAlignment(effectiveCenterTitle);
|
final Alignment titleAlignment = _getTitleAlignment(effectiveCenterTitle);
|
||||||
children.add(Container(
|
children.add(Container(
|
||||||
padding: EdgeInsetsDirectional.only(
|
padding: padding,
|
||||||
start: effectiveCenterTitle ? 0.0 : 72.0,
|
|
||||||
bottom: 16.0
|
|
||||||
),
|
|
||||||
child: Transform(
|
child: Transform(
|
||||||
alignment: titleAlignment,
|
alignment: titleAlignment,
|
||||||
transform: scaleTransform,
|
transform: scaleTransform,
|
||||||
|
@ -114,6 +114,88 @@ void main() {
|
|||||||
|
|
||||||
expect(clipRect.size.height, minExtent);
|
expect(clipRect.size.height, minExtent);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWidgets('FlexibleSpaceBar test titlePadding defaults', (WidgetTester tester) async {
|
||||||
|
Widget buildFrame(TargetPlatform platform, bool centerTitle) {
|
||||||
|
return MaterialApp(
|
||||||
|
theme: ThemeData(platform: platform),
|
||||||
|
home: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
centerTitle: centerTitle,
|
||||||
|
title: const Text('X'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Finder title = find.text('X');
|
||||||
|
final Finder flexibleSpaceBar = find.byType(FlexibleSpaceBar);
|
||||||
|
Offset getTitleBottomLeft() {
|
||||||
|
return Offset(
|
||||||
|
tester.getTopLeft(title).dx,
|
||||||
|
tester.getBottomRight(flexibleSpaceBar).dy - tester.getBottomRight(title).dy,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TargetPlatform.android, null));
|
||||||
|
expect(getTitleBottomLeft(), const Offset(72.0, 16.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TargetPlatform.android, true));
|
||||||
|
expect(getTitleBottomLeft(), const Offset(390.0, 16.0));
|
||||||
|
|
||||||
|
// Clear the widget tree to avoid animating between Android and iOS.
|
||||||
|
await tester.pumpWidget(Container(key: UniqueKey()));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TargetPlatform.iOS, null));
|
||||||
|
expect(getTitleBottomLeft(), const Offset(390.0, 16.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TargetPlatform.iOS, false));
|
||||||
|
expect(getTitleBottomLeft(), const Offset(72.0, 16.0));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('FlexibleSpaceBar test titlePadding override', (WidgetTester tester) async {
|
||||||
|
Widget buildFrame(TargetPlatform platform, bool centerTitle) {
|
||||||
|
return MaterialApp(
|
||||||
|
theme: ThemeData(platform: platform),
|
||||||
|
home: Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
|
titlePadding: EdgeInsets.zero,
|
||||||
|
centerTitle: centerTitle,
|
||||||
|
title: const Text('X'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final Finder title = find.text('X');
|
||||||
|
final Finder flexibleSpaceBar = find.byType(FlexibleSpaceBar);
|
||||||
|
Offset getTitleBottomLeft() {
|
||||||
|
return Offset(
|
||||||
|
tester.getTopLeft(title).dx,
|
||||||
|
tester.getBottomRight(flexibleSpaceBar).dy - tester.getBottomRight(title).dy,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TargetPlatform.android, null));
|
||||||
|
expect(getTitleBottomLeft(), Offset.zero);
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TargetPlatform.android, true));
|
||||||
|
expect(getTitleBottomLeft(), const Offset(390.0, 0.0));
|
||||||
|
|
||||||
|
// Clear the widget tree to avoid animating between Android and iOS.
|
||||||
|
await tester.pumpWidget(Container(key: UniqueKey()));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TargetPlatform.iOS, null));
|
||||||
|
expect(getTitleBottomLeft(), const Offset(390.0, 0.0));
|
||||||
|
|
||||||
|
await tester.pumpWidget(buildFrame(TargetPlatform.iOS, false));
|
||||||
|
expect(getTitleBottomLeft(), Offset.zero);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class TestDelegate extends SliverPersistentHeaderDelegate {
|
class TestDelegate extends SliverPersistentHeaderDelegate {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user