Unverified Commit 6e1d4f9f authored by Taha Tesser's avatar Taha Tesser Committed by GitHub

Fix `SliverAppBar.medium` & `SliverAppBar.large` text scale (#125038)

fixes https://github.com/flutter/flutter/issues/114340

<details> 
<summary>code sample</summary> 

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

/// Flutter code sample for [SliverAppBar.medium].

void main() {
  runApp(const AppBarMediumApp());
}

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      theme: ThemeData(
        useMaterial3: true,
      ),
      home: MediaQuery(
        data: MediaQuery.of(context).copyWith(textScaleFactor: 3.0),
        child: Material(
          child: CustomScrollView(
            slivers: <Widget>[
              SliverAppBar.medium(
                leading:
                    IconButton(icon: const Icon(Icons.menu), onPressed: () {}),
                title: const Text('Medium App Bar'),
                actions: <Widget>[
                  IconButton(icon: const Icon(Icons.more_vert), onPressed: () {}),
                ],
              ),
              // SliverAppBar.large(
              //   leading:
              //       IconButton(icon: const Icon(Icons.menu), onPressed: () {}),
              //   title: const Text('Large App Bar'),
              //   actions: <Widget>[
              //     IconButton(
              //         icon: const Icon(Icons.more_vert), onPressed: () {}),
              //   ],
              // ),
              // Just some content big enough to have something to scroll.
              SliverToBoxAdapter(
                child: Card(
                  child: SizedBox(
                    height: 1200,
                    child: Padding(
                      padding: const EdgeInsets.fromLTRB(8, 100, 8, 100),
                      child: Text(
                        'Here be scrolling content...',
                        style: Theme.of(context).textTheme.headlineSmall,
                      ),
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

``` 
	
</details>

### Before
|  Medium App Bar - `textScaleFactor: 3.0` |   Large App Bar - `textScaleFactor.30` |
| --------------- | --------------- |
| <img src="https://user-images.githubusercontent.com/48603081/232815191-ab42523b-d710-4c93-a889-e9c92ca472c8.png" height="450" /> | <img src="https://user-images.githubusercontent.com/48603081/232815232-104c208d-f1dd-404e-9218-5dfb61244d56.png" height="450" /> |

### After
|  Medium App Bar - `textScaleFactor: 3.0` |   Large App Bar - `textScaleFactor.30` |
| --------------- | --------------- |
| <img src="https://user-images.githubusercontent.com/48603081/232815733-8b8af94f-197f-427a-bbb9-bc6cd0173658.png" height="450" /> | <img src="https://user-images.githubusercontent.com/48603081/232815758-2c336d14-085b-4e91-8b93-748a40822ea6.png" height="450" /> |
parent 8395a2b2
......@@ -2101,10 +2101,11 @@ class _ScrollUnderFlexibleSpace extends StatelessWidget {
late final ThemeData theme = Theme.of(context);
late final AppBarTheme appBarTheme = AppBarTheme.of(context);
final AppBarTheme defaults = theme.useMaterial3 ? _AppBarDefaultsM3(context) : _AppBarDefaultsM2(context);
final double textScaleFactor = math.min(MediaQuery.textScaleFactorOf(context), _kMaxTitleTextScaleFactor); // TODO(tahatesser): Add link to Material spec when available, https://github.com/flutter/flutter/issues/58769.
final FlexibleSpaceBarSettings settings = context.dependOnInheritedWidgetOfExactType<FlexibleSpaceBarSettings>()!;
final double topPadding = primary ? MediaQuery.viewPaddingOf(context).top : 0;
final double collapsedHeight = settings.minExtent - topPadding - bottomHeight;
final double scrollUnderHeight = settings.maxExtent - settings.minExtent + bottomHeight;
final double scrollUnderHeight = settings.maxExtent - (settings.minExtent / textScaleFactor) + bottomHeight;
final _ScrollUnderFlexibleConfig config;
switch (variant) {
case _ScrollUnderFlexibleVariant.medium:
......@@ -2144,12 +2145,20 @@ class _ScrollUnderFlexibleSpace extends StatelessWidget {
padding.left,
0,
padding.right,
adjustBottomPadding,
adjustBottomPadding / textScaleFactor,
);
}
return padding;
}
return Column(
// Set maximum text scale factor to [_kMaxTitleTextScaleFactor] for the
// title to keep the visual hierarchy the same even with larger font
// sizes. To opt out, wrap the [title] widget in a [MediaQuery] widget
// with [MediaQueryData.textScaleFactor] set to
// `MediaQuery.textScaleFactorOf(context)`.
return MediaQuery(
data: MediaQuery.of(context).copyWith(textScaleFactor: textScaleFactor),
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.only(top: collapsedHeight + topPadding),
......@@ -2169,6 +2178,7 @@ class _ScrollUnderFlexibleSpace extends StatelessWidget {
),
),
],
),
);
}
}
......
......@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:flutter/services.dart';
......@@ -4649,6 +4650,190 @@ void main() {
expect(appBarHeight(tester), collapsedAppBarHeight + bottomHeight);
});
testWidgets('SliverAppBar.medium expanded title has upper limit on text scaling', (WidgetTester tester) async {
const String title = 'Medium AppBar';
Widget buildAppBar({double textScaleFactor = 1.0}) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: MediaQuery(
data: MediaQueryData(textScaleFactor: textScaleFactor),
child: Material(
child: CustomScrollView(
slivers: <Widget>[
const SliverAppBar.medium(
title: Text(title),
),
SliverToBoxAdapter(
child: Container(
height: 1200,
color: Colors.orange[400],
),
),
],
),
),
),
);
}
await tester.pumpWidget(buildAppBar());
final Finder expandedTitle = find.text(title).first;
expect(tester.getRect(expandedTitle).height, closeTo(31.9, 0.1));
await tester.pumpWidget(buildAppBar(textScaleFactor: 2.0));
expect(tester.getRect(expandedTitle).height, closeTo(43.0, 0.1));
await tester.pumpWidget(buildAppBar(textScaleFactor: 3.0));
expect(tester.getRect(expandedTitle).height, closeTo(43.0, 0.1));
});
testWidgets('SliverAppBar.large expanded title has upper limit on text scaling', (WidgetTester tester) async {
const String title = 'Large AppBar';
Widget buildAppBar({double textScaleFactor = 1.0}) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: MediaQuery(
data: MediaQueryData(textScaleFactor: textScaleFactor),
child: Material(
child: CustomScrollView(
slivers: <Widget>[
const SliverAppBar.large(
title: Text(title),
),
SliverToBoxAdapter(
child: Container(
height: 1200,
color: Colors.orange[400],
),
),
],
),
),
),
);
}
await tester.pumpWidget(buildAppBar());
// TODO(tahatesser): https://github.com/flutter/flutter/issues/99933
// A bug in the HTML renderer and/or Chrome 96+ causes a
// discrepancy in the paragraph height.
const bool hasIssue99933 = kIsWeb && !bool.fromEnvironment('FLUTTER_WEB_USE_SKIA');
final Finder expandedTitle = find.text(title).first;
expect(
tester.getRect(expandedTitle).height,
closeTo( hasIssue99933 ? 37.0 : 36.0, 0.1),
);
await tester.pumpWidget(buildAppBar(textScaleFactor: 2.0));
expect(tester.getRect(expandedTitle).height, closeTo(48.0, 0.1));
await tester.pumpWidget(buildAppBar(textScaleFactor: 3.0));
expect(tester.getRect(expandedTitle).height, closeTo(48.0, 0.1));
});
testWidgets('SliverAppBar.medium expanded title position is adjusted with textScaleFactor', (WidgetTester tester) async {
const String title = 'Medium AppBar';
Widget buildAppBar({double textScaleFactor = 1.0}) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: MediaQuery(
data: MediaQueryData(textScaleFactor: textScaleFactor),
child: Material(
child: CustomScrollView(
slivers: <Widget>[
const SliverAppBar.medium(
title: Text(title),
),
SliverToBoxAdapter(
child: Container(
height: 1200,
color: Colors.orange[400],
),
),
],
),
),
),
);
}
await tester.pumpWidget(buildAppBar());
final Finder expandedTitle = find.text(title).first;
Offset titleTop = tester.getTopLeft(expandedTitle);
expect(titleTop.dy, 64.0);
Offset titleBottom = tester.getBottomLeft(expandedTitle);
expect(titleBottom.dy, closeTo(96.0, 0.1));
await tester.pumpWidget(buildAppBar(textScaleFactor: 2.0));
titleTop = tester.getTopLeft(expandedTitle);
expect(titleTop.dy, closeTo(57.0, 0.1));
titleBottom = tester.getBottomLeft(expandedTitle);
expect(titleBottom.dy, closeTo(100.0, 0.1));
await tester.pumpWidget(buildAppBar(textScaleFactor: 3.0));
titleTop = tester.getTopLeft(expandedTitle);
expect(titleTop.dy, closeTo(57.0, 0.1));
titleBottom = tester.getBottomLeft(expandedTitle);
expect(titleBottom.dy, closeTo(100.0, 0.1));
});
testWidgets('SliverAppBar.large expanded title position is adjusted with textScaleFactor', (WidgetTester tester) async {
const String title = 'Large AppBar';
Widget buildAppBar({double textScaleFactor = 1.0}) {
return MaterialApp(
theme: ThemeData(useMaterial3: true),
home: MediaQuery(
data: MediaQueryData(textScaleFactor: textScaleFactor),
child: Material(
child: CustomScrollView(
slivers: <Widget>[
const SliverAppBar.large(
title: Text(title),
),
SliverToBoxAdapter(
child: Container(
height: 1200,
color: Colors.orange[400],
),
),
],
),
),
),
);
}
await tester.pumpWidget(buildAppBar());
// TODO(tahatesser): https://github.com/flutter/flutter/issues/99933
// A bug in the HTML renderer and/or Chrome 96+ causes a
// discrepancy in the paragraph height.
const bool hasIssue99933 = kIsWeb && !bool.fromEnvironment('FLUTTER_WEB_USE_SKIA');
final Finder expandedTitle = find.text(title).first;
Offset titleTop = tester.getTopLeft(expandedTitle);
expect(titleTop.dy, closeTo(hasIssue99933 ? 91.0 : 92.0, 0.1));
Offset titleBottom = tester.getBottomLeft(expandedTitle);
expect(titleBottom.dy, closeTo(128.0, 0.1));
await tester.pumpWidget(buildAppBar(textScaleFactor: 2.0));
titleTop = tester.getTopLeft(expandedTitle);
expect(titleTop.dy, closeTo(86.1, 0.1));
titleBottom = tester.getBottomLeft(expandedTitle);
expect(titleBottom.dy, closeTo(134.1, 0.1));
await tester.pumpWidget(buildAppBar(textScaleFactor: 3.0));
titleTop = tester.getTopLeft(expandedTitle);
expect(titleTop.dy, closeTo(86.1, 0.1));
titleBottom = tester.getBottomLeft(expandedTitle);
expect(titleBottom.dy, closeTo(134.1, 0.1));
});
group('AppBar.forceMaterialTransparency', () {
Material getAppBarMaterial(WidgetTester tester) {
return tester.widget<Material>(find
......
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