Skip to content

Commit f2be9bc

Browse files
authored
Fix Tab indicator image configuration doesn't inherit device pixel ratio (#146812)
fixes [The image for the indicator of the TabBar does not auto-adapt to different resolutions](flutter/flutter#145204) ### Description This PR provides device pixel ratio to the tab indicator painter.
1 parent 0240077 commit f2be9bc

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

packages/flutter/lib/src/material/tabs.dart

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ class _IndicatorPainter extends CustomPainter {
442442
this.dividerColor,
443443
this.dividerHeight,
444444
required this.showDivider,
445+
this.devicePixelRatio,
445446
}) : super(repaint: controller.animation) {
446447
// TODO(polina-c): stop duplicating code across disposables
447448
// https://github.com/flutter/flutter/issues/137435
@@ -466,6 +467,7 @@ class _IndicatorPainter extends CustomPainter {
466467
final Color? dividerColor;
467468
final double? dividerHeight;
468469
final bool showDivider;
470+
final double? devicePixelRatio;
469471

470472
// _currentTabOffsets and _currentTextDirection are set each time TabBar
471473
// layout is completed. These values can be null when TabBar contains no
@@ -562,6 +564,7 @@ class _IndicatorPainter extends CustomPainter {
562564
final ImageConfiguration configuration = ImageConfiguration(
563565
size: _currentRect!.size,
564566
textDirection: _currentTextDirection,
567+
devicePixelRatio: devicePixelRatio,
565568
);
566569
if (showDivider && dividerHeight !> 0) {
567570
final Paint dividerPaint = Paint()..color = dividerColor!..strokeWidth = dividerHeight!;
@@ -1433,6 +1436,7 @@ class _TabBarState extends State<TabBar> {
14331436
dividerColor: widget.dividerColor ?? tabBarTheme.dividerColor ?? _defaults.dividerColor,
14341437
dividerHeight: widget.dividerHeight ?? tabBarTheme.dividerHeight ?? _defaults.dividerHeight,
14351438
showDivider: theme.useMaterial3 && !widget.isScrollable,
1439+
devicePixelRatio: MediaQuery.devicePixelRatioOf(context),
14361440
);
14371441

14381442
oldPainter?.dispose();

packages/flutter/test/material/tabs_test.dart

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ Widget buildFrame({
5050
TextDirection textDirection = TextDirection.ltr,
5151
TabAlignment? tabAlignment,
5252
TabBarTheme? tabBarTheme,
53+
Decoration? indicator,
5354
bool? useMaterial3,
5455
}) {
5556
if (secondaryTabBar) {
@@ -88,6 +89,7 @@ Widget buildFrame({
8889
indicatorColor: indicatorColor,
8990
padding: padding,
9091
tabAlignment: tabAlignment,
92+
indicator: indicator,
9193
),
9294
),
9395
);
@@ -7075,4 +7077,50 @@ void main() {
70757077
expect(find.text('View 0'), findsNothing);
70767078
expect(find.text('View 2'), findsOneWidget);
70777079
});
7080+
7081+
testWidgets('Tab indicator painter image configuration', (WidgetTester tester) async {
7082+
final List<String> tabs = <String>['A', 'B'];
7083+
final TestIndicatorDecoration decoration = TestIndicatorDecoration();
7084+
7085+
Widget buildTabs({
7086+
TextDirection textDirection = TextDirection.ltr,
7087+
double ratio = 1.0,
7088+
}) {
7089+
return MaterialApp(
7090+
home: MediaQuery(
7091+
data: MediaQueryData(devicePixelRatio: ratio),
7092+
child: Directionality(
7093+
textDirection: textDirection,
7094+
child: DefaultTabController(
7095+
length: tabs.length,
7096+
child: Scaffold(
7097+
appBar: AppBar(
7098+
bottom: TabBar(
7099+
indicator: decoration,
7100+
tabs: tabs.map((String tab) => Tab(text: tab)).toList(),
7101+
),
7102+
),
7103+
),
7104+
),
7105+
),
7106+
),
7107+
);
7108+
}
7109+
7110+
await tester.pumpWidget(buildTabs());
7111+
7112+
ImageConfiguration config = decoration.painters.last.lastConfiguration!;
7113+
expect(config.size?.width, closeTo(14.1, 0.1));
7114+
expect(config.size?.height, equals(48.0));
7115+
expect(config.textDirection, TextDirection.ltr);
7116+
expect(config.devicePixelRatio, 1.0);
7117+
7118+
await tester.pumpWidget(buildTabs(textDirection: TextDirection.rtl, ratio: 2.33));
7119+
7120+
config = decoration.painters.last.lastConfiguration!;
7121+
expect(config.size?.width, closeTo(14.1, 0.1));
7122+
expect(config.size?.height, equals(48.0));
7123+
expect(config.textDirection, TextDirection.rtl);
7124+
expect(config.devicePixelRatio, 2.33);
7125+
});
70787126
}

packages/flutter/test/material/tabs_utils.dart

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,3 +228,24 @@ class _TabAlwaysKeepAliveWidgetState extends State<TabAlwaysKeepAliveWidget> wit
228228
return Text(TabAlwaysKeepAliveWidget.text);
229229
}
230230
}
231+
232+
// This decoration is used to test the indicator decoration image configuration.
233+
class TestIndicatorDecoration extends Decoration {
234+
final List<TestIndicatorBoxPainter> painters = <TestIndicatorBoxPainter>[];
235+
236+
@override
237+
BoxPainter createBoxPainter([VoidCallback? onChanged]) {
238+
final TestIndicatorBoxPainter painter = TestIndicatorBoxPainter();
239+
painters.add(painter);
240+
return painter;
241+
}
242+
}
243+
244+
class TestIndicatorBoxPainter extends BoxPainter {
245+
ImageConfiguration? lastConfiguration;
246+
247+
@override
248+
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
249+
lastConfiguration = configuration;
250+
}
251+
}

0 commit comments

Comments
 (0)