Unverified Commit ceeaf98e authored by Bruno Leroux's avatar Bruno Leroux Committed by GitHub

Fix navigation rail with long labels misplaced highlights (#128324)

parent ddfe8a35
...@@ -585,6 +585,7 @@ class _RailDestination extends StatelessWidget { ...@@ -585,6 +585,7 @@ class _RailDestination extends StatelessWidget {
final bool material3 = theme.useMaterial3; final bool material3 = theme.useMaterial3;
final EdgeInsets destinationPadding = (padding ?? EdgeInsets.zero).resolve(Directionality.of(context)); final EdgeInsets destinationPadding = (padding ?? EdgeInsets.zero).resolve(Directionality.of(context));
Offset indicatorOffset; Offset indicatorOffset;
bool applyXOffset = false;
final Widget themedIcon = IconTheme( final Widget themedIcon = IconTheme(
data: disabled data: disabled
...@@ -645,6 +646,7 @@ class _RailDestination extends StatelessWidget { ...@@ -645,6 +646,7 @@ class _RailDestination extends StatelessWidget {
); );
} else { } else {
final Animation<double> labelFadeAnimation = extendedTransitionAnimation.drive(CurveTween(curve: const Interval(0.0, 0.25))); final Animation<double> labelFadeAnimation = extendedTransitionAnimation.drive(CurveTween(curve: const Interval(0.0, 0.25)));
applyXOffset = true;
content = Padding( content = Padding(
padding: padding ?? EdgeInsets.zero, padding: padding ?? EdgeInsets.zero,
child: ConstrainedBox( child: ConstrainedBox(
...@@ -775,6 +777,7 @@ class _RailDestination extends StatelessWidget { ...@@ -775,6 +777,7 @@ class _RailDestination extends StatelessWidget {
hoverColor: colors.primary.withOpacity(0.04), hoverColor: colors.primary.withOpacity(0.04),
useMaterial3: material3, useMaterial3: material3,
indicatorOffset: indicatorOffset, indicatorOffset: indicatorOffset,
applyXOffset: applyXOffset,
child: content, child: content,
), ),
), ),
...@@ -797,6 +800,7 @@ class _IndicatorInkWell extends InkResponse { ...@@ -797,6 +800,7 @@ class _IndicatorInkWell extends InkResponse {
super.hoverColor, super.hoverColor,
required this.useMaterial3, required this.useMaterial3,
required this.indicatorOffset, required this.indicatorOffset,
required this.applyXOffset,
}) : super( }) : super(
containedInkWell: true, containedInkWell: true,
highlightShape: BoxShape.rectangle, highlightShape: BoxShape.rectangle,
...@@ -805,14 +809,19 @@ class _IndicatorInkWell extends InkResponse { ...@@ -805,14 +809,19 @@ class _IndicatorInkWell extends InkResponse {
); );
final bool useMaterial3; final bool useMaterial3;
// The offset used to position Ink highlight.
final Offset indicatorOffset; final Offset indicatorOffset;
// Whether the horizontal offset from indicatorOffset should be used to position Ink highlight.
// If true, Ink highlight uses the indicator horizontal offset. If false, Ink highlight is centered horizontally.
final bool applyXOffset;
@override @override
RectCallback? getRectCallback(RenderBox referenceBox) { RectCallback? getRectCallback(RenderBox referenceBox) {
if (useMaterial3) { if (useMaterial3) {
final double indicatorHorizontalCenter = applyXOffset ? indicatorOffset.dx : referenceBox.size.width / 2;
return () { return () {
return Rect.fromLTWH( return Rect.fromLTWH(
indicatorOffset.dx - (_kCircularIndicatorDiameter / 2), indicatorHorizontalCenter - (_kCircularIndicatorDiameter / 2),
indicatorOffset.dy, indicatorOffset.dy,
_kCircularIndicatorDiameter, _kCircularIndicatorDiameter,
_kIndicatorHeight, _kIndicatorHeight,
......
...@@ -3048,6 +3048,81 @@ void main() { ...@@ -3048,6 +3048,81 @@ void main() {
); );
}); });
testWidgets('NavigationRail indicator renders properly with long labels', (WidgetTester tester) async {
// This is a regression test for https://github.com/flutter/flutter/issues/128005.
await _pumpNavigationRail(
tester,
navigationRail: NavigationRail(
selectedIndex: 1,
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.favorite_border),
selectedIcon: Icon(Icons.favorite),
label: Text('ABCDEFGHIJKLMNOPQRSTUVWXYZ'),
),
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.bookmark),
label: Text('ABC'),
),
],
labelType: NavigationRailLabelType.all,
),
);
final TestGesture gesture = await tester.createGesture(kind: PointerDeviceKind.mouse);
await gesture.addPointer();
await gesture.moveTo(tester.getCenter(find.byIcon(Icons.favorite_border)));
await tester.pumpAndSettle();
final RenderObject inkFeatures = tester.allRenderObjects.firstWhere((RenderObject object) => object.runtimeType.toString() == '_RenderInkFeatures');
// Default values from M3 specification.
const double indicatorHeight = 32.0;
const double destinationWidth = 72.0;
const double destinationHorizontalPadding = 8.0;
const double indicatorWidth = destinationWidth - 2 * destinationHorizontalPadding; // 56.0
// The navigation rail width is larger than default because of the first destination long label.
final double railWidth = tester.getSize(find.byType(NavigationRail)).width;
// Expected indicator position.
final double indicatorLeft = (railWidth - indicatorWidth) / 2;
final double indicatorRight = (railWidth + indicatorWidth) / 2;
final Rect indicatorRect = Rect.fromLTRB(indicatorLeft, 0.0, indicatorRight, indicatorHeight);
final Rect includedRect = indicatorRect;
final Rect excludedRect = includedRect.inflate(10);
expect(
inkFeatures,
paints
..clipPath(
pathMatcher: isPathThat(
includes: <Offset>[
includedRect.centerLeft,
includedRect.topCenter,
includedRect.centerRight,
includedRect.bottomCenter,
],
excludes: <Offset>[
excludedRect.centerLeft,
excludedRect.topCenter,
excludedRect.centerRight,
excludedRect.bottomCenter,
],
),
)
..rect(
rect: indicatorRect,
color: const Color(0x0a6750a4),
)
..rrect(
rrect: RRect.fromLTRBR(indicatorLeft, 72.0, indicatorRight, 104.0, const Radius.circular(16)),
color: const Color(0xffe8def8),
),
);
});
testWidgets('NavigationRail indicator scale transform', (WidgetTester tester) async { testWidgets('NavigationRail indicator scale transform', (WidgetTester tester) async {
int selectedIndex = 0; int selectedIndex = 0;
Future<void> buildWidget() async { Future<void> buildWidget() async {
......
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