Unverified Commit e20d34c3 authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Fix `FlexibleSpaceBar` centered title position and title color (#140883)

fixes [Invisible SliverAppBar title in Material 3 light theme](https://github.com/flutter/flutter/issues/138296) 
fixes [`FlexibleSpaceBar` title is misaligned without the leading widget](https://github.com/flutter/flutter/issues/138608)

Previous attempt https://github.com/flutter/flutter/pull/138611

--- 

### Description

 - fixes the `FlexibleSpaceBar` centered title position when there is a leading widget.
 - fixes the `FlexibleSpaceBar` title color for Material 3.
 - Added documentation when using a long `FlexibleSpaceBar` title and update its test.
 - Improved documentation of default title padding.

### Code sample

### Code sample

<details>
<summary>expand to view the code sample</summary> 

```dart
import 'package:flutter/material.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return const MaterialApp(
      debugShowCheckedModeBanner: false,
      home: Example(),
    );
  }
}

class Example extends StatelessWidget {
  const Example({super.key});

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      body: SafeArea(
          child: CustomScrollView(
        slivers: <Widget>[
          SliverAppBar(
            leading: Icon(Icons.favorite_rounded),
            flexibleSpace: FlexibleSpaceBar(
              title: ColoredBox(
                color: Color(0xffff0000),
                child: Text('SliverAppBar'),
              ),
            ),
          ),
        ],
      )),
    );
  }
}
```

</details>

###  Before

![Screenshot 2024-01-03 at 18 02 25](https://github.com/flutter/flutter/assets/48603081/92ae1062-c78f-4005-8e28-85af617acd60)

### After

![Screenshot 2024-01-03 at 18 02 16](https://github.com/flutter/flutter/assets/48603081/2ef97108-9b50-44f7-a303-018ff1b28db6)
parent 62da6525
......@@ -99,6 +99,10 @@ class FlexibleSpaceBar extends StatefulWidget {
/// Whether the title should be centered.
///
/// If the length of the title is greater than the available space, set
/// this property to false. This aligns the title to the start of the
/// flexible space bar and applies [titlePadding] to the title.
///
/// By default this property is true if the current target platform
/// is [TargetPlatform.iOS] or [TargetPlatform.macOS], false otherwise.
final bool? centerTitle;
......@@ -120,9 +124,13 @@ class FlexibleSpaceBar extends StatefulWidget {
/// 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.
/// If [centerTitle] is true, then the title is centered within the
/// flexible space bar with a bottom padding of 16.0 pixels.
///
/// If [centerTitle] is false and [FlexibleSpaceBarSettings.hasLeading] is true,
/// then the title is aligned to the start of the flexible space bar with the
/// [titlePadding] applied. If [titlePadding] is null, then defaults to start
/// padding of 72.0 pixels and bottom padding of 16.0 pixels.
final EdgeInsetsGeometry? titlePadding;
/// Defines how much the title is scaled when the FlexibleSpaceBar is expanded
......@@ -316,14 +324,15 @@ class _FlexibleSpaceBarState extends State<FlexibleSpaceBar> {
final double opacity = settings.toolbarOpacity;
if (opacity > 0.0) {
TextStyle titleStyle = theme.primaryTextTheme.titleLarge!;
TextStyle titleStyle = theme.useMaterial3 ? theme.textTheme.titleLarge! : theme.primaryTextTheme.titleLarge!;
titleStyle = titleStyle.copyWith(
color: titleStyle.color!.withOpacity(opacity),
);
final bool effectiveCenterTitle = _getEffectiveCenterTitle(theme);
final double leadingPadding = (settings.hasLeading ?? true) ? 72.0 : 0.0;
final EdgeInsetsGeometry padding = widget.titlePadding ??
EdgeInsetsDirectional.only(
start: effectiveCenterTitle && !(settings.hasLeading ?? false) ? 0.0 : 72.0,
start: effectiveCenterTitle ? 0.0 : leadingPadding,
bottom: 16.0,
);
final double scaleValue = Tween<double>(begin: widget.expandedTitleScale, end: 1.0).transform(t);
......
......@@ -719,7 +719,6 @@ void main() {
await tester.pumpWidget(buildFrame(TargetPlatform.macOS, false));
expect(getTitleBottomLeft(), const Offset(72.0, 16.0));
});
testWidgets('FlexibleSpaceBar test titlePadding override', (WidgetTester tester) async {
......@@ -830,7 +829,9 @@ void main() {
leading: const Icon(Icons.menu),
flexibleSpace: FlexibleSpaceBar(
title: Text('title ' * 10),
centerTitle: true,
// Set centerTitle to false to create a gap between the leading widget
// and the long title.
centerTitle: false,
),
),
) as FlexibleSpaceBarSettings;
......@@ -861,54 +862,6 @@ void main() {
expect(tester.getTopLeft(find.byType(Text)).dx, closeTo(72.0, 0.01));
});
// This is a regression test for https://github.com/flutter/flutter/issues/132030.
testWidgets('Long centered FlexibleSpaceBar.title respects leading widget', (WidgetTester tester) async {
// Test start position of a long title when the leading widget is
// shown by default and the long title is centered.
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
drawer: const Drawer(),
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
flexibleSpace: FlexibleSpaceBar(
title: Text('Title ' * 10),
centerTitle: true,
),
),
],
),
),
),
);
expect(tester.getTopLeft(find.byType(Text)).dx, 72.0);
// Test start position of a long title when the leading widget is provided
// and the long title is centered.
await tester.pumpWidget(
MaterialApp(
home: Scaffold(
body: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
leading: const Icon(Icons.menu),
flexibleSpace: FlexibleSpaceBar(
title: Text('Title ' * 10),
centerTitle: true,
),
),
],
),
),
),
);
await tester.pumpAndSettle();
expect(tester.getTopLeft(find.byType(Text)).dx, 72.0);
});
// This is a regression test for https://github.com/flutter/flutter/issues/135698.
testWidgets('_FlexibleSpaceHeaderOpacity with near zero opacity avoids compositing', (WidgetTester tester) async {
await tester.pumpWidget(
......@@ -948,6 +901,55 @@ void main() {
expect(tester.takeException(), isNull);
}, variant: TargetPlatformVariant.mobile());
// This is a regression test for https://github.com/flutter/flutter/issues/138608.
testWidgets('FlexibleSpaceBar centers title with a leading widget', (WidgetTester tester) async {
await tester.pumpWidget(
const MaterialApp(
home: Material(
child: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
leading: Icon(Icons.menu),
flexibleSpace: FlexibleSpaceBar(
centerTitle: true,
title: Text('X'),
),
),
],
),
),
),
);
final Offset appBarCenter = tester.getCenter(find.byType(AppBar));
final Offset titleCenter = tester.getCenter(find.text('X'));
expect(appBarCenter.dx, titleCenter.dx);
});
// This is a regression test for https://github.com/flutter/flutter/issues/138296.
testWidgets('Material3 - Default title color', (WidgetTester tester) async {
final ThemeData theme = ThemeData();
await tester.pumpWidget(
MaterialApp(
theme: theme, // Provide the expected theme data.
home: const Material(
child: CustomScrollView(
slivers: <Widget>[
SliverAppBar(
flexibleSpace: FlexibleSpaceBar(
title: Text('Title'),
),
),
],
),
),
),
);
final DefaultTextStyle textStyle = DefaultTextStyle.of(tester.element(find.text('Title')));
expect(textStyle.style.color, theme.textTheme.titleLarge!.color);
});
}
class TestDelegate extends SliverPersistentHeaderDelegate {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment