Skip to content

Commit bd0e203

Browse files
authored
Fix ink features painting in TabBar. (flutter#177155)
Fixes flutter#141269 ## Description - Fixes ink features painting outside of the `TabBar` bounds | BEFORE | AFTER | | - | - | | <video alt="before" src="https://github.com/user-attachments/assets/954ce655-b400-47f7-a641-5effe431cfa4" /> | <video alt="after" src="https://github.com/user-attachments/assets/283a64e9-4851-4f9a-98ad-a89d8fd4edb1" /> | ## Pre-launch Checklist - [X] I read the [Contributor Guide] and followed the process outlined there for submitting PRs. - [X] I read the [Tree Hygiene] wiki page, which explains my responsibilities. - [X] I read and followed the [Flutter Style Guide], including [Features we expect every widget to implement]. - [X] I signed the [CLA]. - [X] I listed at least one issue that this PR fixes in the description above. - [ ] I updated/added relevant documentation (doc comments with `///`). - [X] I added new tests to check the change I am making, or this PR is [test-exempt]. - [X] I followed the [breaking change policy] and added [Data Driven Fixes] where supported. - [X] All existing and new tests are passing. If you need help, consider asking for advice on the #hackers-new channel on [Discord]. <!-- Links --> [Contributor Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#overview [Tree Hygiene]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md [test-exempt]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#tests [Flutter Style Guide]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md [Features we expect every widget to implement]: https://github.com/flutter/flutter/blob/main/docs/contributing/Style-guide-for-Flutter-repo.md#features-we-expect-every-widget-to-implement [CLA]: https://cla.developers.google.com/ [flutter/tests]: https://github.com/flutter/tests [breaking change policy]: https://github.com/flutter/flutter/blob/main/docs/contributing/Tree-hygiene.md#handling-breaking-changes [Discord]: https://github.com/flutter/flutter/blob/main/docs/contributing/Chat.md [Data Driven Fixes]: https://github.com/flutter/flutter/blob/main/docs/contributing/Data-driven-Fixes.md
1 parent 4ddd558 commit bd0e203

File tree

3 files changed

+54
-8
lines changed

3 files changed

+54
-8
lines changed

examples/api/test/material/app_bar/app_bar.3_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ void main() {
1111
WidgetTester tester,
1212
) async {
1313
Material getMaterial() => tester.widget<Material>(
14-
find.descendant(of: find.byType(AppBar), matching: find.byType(Material)),
14+
find.descendant(of: find.byType(AppBar), matching: find.byType(Material)).first,
1515
);
1616

1717
await tester.pumpWidget(const example.AppBarApp());

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

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1612,7 +1612,6 @@ class _TabBarState extends State<TabBar> {
16121612
@override
16131613
void didChangeDependencies() {
16141614
super.didChangeDependencies();
1615-
assert(debugCheckHasMaterial(context));
16161615
_updateTabController();
16171616
_initIndicatorPainter();
16181617
}
@@ -2055,11 +2054,14 @@ class _TabBarState extends State<TabBar> {
20552054
tabBar = Padding(padding: widget.padding!, child: tabBar);
20562055
}
20572056

2058-
return MediaQuery(
2059-
data: MediaQuery.of(
2060-
context,
2061-
).copyWith(textScaler: widget.textScaler ?? tabBarTheme.textScaler),
2062-
child: tabBar,
2057+
return Material(
2058+
type: MaterialType.transparency,
2059+
child: MediaQuery(
2060+
data: MediaQuery.of(
2061+
context,
2062+
).copyWith(textScaler: widget.textScaler ?? tabBarTheme.textScaler),
2063+
child: tabBar,
2064+
),
20632065
);
20642066
}
20652067
}

packages/flutter/test/material/tabs_test.dart

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ void main() {
157157
phase: EnginePhase.build,
158158
);
159159

160-
expect(tester.renderObject(find.byType(CustomPaint)).debugNeedsPaint, true);
160+
expect(tester.renderObject(find.byType(CustomPaint).last).debugNeedsPaint, true);
161161
});
162162

163163
testWidgets('tab semantics role test', (WidgetTester tester) async {
@@ -9278,4 +9278,48 @@ void main() {
92789278
(focus: false, index: 2), // Third tab loses focus
92799279
]);
92809280
});
9281+
9282+
// Regression test for https://github.com/flutter/flutter/issues/141269.
9283+
testWidgets('Ink features are painted on inner Material', (WidgetTester tester) async {
9284+
await tester.pumpWidget(
9285+
MaterialApp(
9286+
home: Material(
9287+
child: Center(
9288+
child: DefaultTabController(
9289+
length: 10,
9290+
child: TabBar(
9291+
isScrollable: true,
9292+
tabs: <Widget>[for (int i = 1; i <= 10; i++) Tab(text: 'Tab $i')],
9293+
),
9294+
),
9295+
),
9296+
),
9297+
),
9298+
);
9299+
9300+
expect(find.byType(Material), findsNWidgets(2));
9301+
9302+
// Material outside the TabBar.
9303+
final MaterialInkController outerMaterial = Material.of(tester.element(find.byType(TabBar)));
9304+
// Material directly wrapping the TabBar.
9305+
final MaterialInkController innerMaterial = Material.of(
9306+
tester.firstElement(
9307+
find.descendant(of: find.byType(TabBar), matching: find.byType(Semantics)),
9308+
),
9309+
);
9310+
9311+
expect(outerMaterial, isNot(same(innerMaterial)));
9312+
expect((outerMaterial as dynamic).debugInkFeatures, isNull);
9313+
expect((innerMaterial as dynamic).debugInkFeatures, isNull);
9314+
9315+
// Hover over the first tab to trigger the ink highlight.
9316+
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
9317+
await gesture.addPointer(location: tester.getCenter(find.text('Tab 1')));
9318+
addTearDown(gesture.removePointer);
9319+
await tester.pump();
9320+
9321+
// Only the inner Material should have ink features.
9322+
expect((outerMaterial as dynamic).debugInkFeatures, isNull);
9323+
expect((innerMaterial as dynamic).debugInkFeatures, hasLength(1));
9324+
});
92819325
}

0 commit comments

Comments
 (0)