mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
fix[widget_inspector]: Widget Inspector Directionality & Move button tooltip. (#169425)
Fix Widget Inspector buttons direction & arrow button tooltip text on when the App locale is RTL: Before:   After:     ## 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. - [x] 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 --------- Co-authored-by: Kenzie Davisson <43759233+kenzieschmoll@users.noreply.github.com>
This commit is contained in:
parent
03dbf1a99c
commit
ec17f9b297
@ -550,12 +550,12 @@ class _CupertinoAppState extends State<CupertinoApp> {
|
||||
BuildContext context, {
|
||||
required VoidCallback onPressed,
|
||||
required String semanticsLabel,
|
||||
bool isLeftAligned = true,
|
||||
bool usesDefaultAlignment = true,
|
||||
}) {
|
||||
return _CupertinoInspectorButton.iconOnly(
|
||||
onPressed: onPressed,
|
||||
semanticsLabel: semanticsLabel,
|
||||
icon: isLeftAligned ? CupertinoIcons.arrow_right : CupertinoIcons.arrow_left,
|
||||
icon: usesDefaultAlignment ? CupertinoIcons.arrow_right : CupertinoIcons.arrow_left,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -951,12 +951,12 @@ class _MaterialAppState extends State<MaterialApp> {
|
||||
BuildContext context, {
|
||||
required VoidCallback onPressed,
|
||||
required String semanticsLabel,
|
||||
bool isLeftAligned = true,
|
||||
bool usesDefaultAlignment = true,
|
||||
}) {
|
||||
return _MaterialInspectorButton.iconOnly(
|
||||
onPressed: onPressed,
|
||||
semanticsLabel: semanticsLabel,
|
||||
icon: isLeftAligned ? Icons.arrow_right : Icons.arrow_left,
|
||||
icon: usesDefaultAlignment ? Icons.arrow_right : Icons.arrow_left,
|
||||
isDarkTheme: _isDarkTheme(context),
|
||||
);
|
||||
}
|
||||
|
||||
@ -55,7 +55,7 @@ typedef MoveExitWidgetSelectionButtonBuilder =
|
||||
BuildContext context, {
|
||||
required VoidCallback onPressed,
|
||||
required String semanticsLabel,
|
||||
bool isLeftAligned,
|
||||
bool usesDefaultAlignment,
|
||||
});
|
||||
|
||||
/// Signature for the builder callback used by
|
||||
@ -3737,7 +3737,11 @@ class _WidgetInspectorButtonGroupState extends State<_WidgetInspectorButtonGroup
|
||||
|
||||
String? _tooltipMessage;
|
||||
|
||||
bool _leftAligned = true;
|
||||
/// Indicates whether the button is using the default alignment based on text direction.
|
||||
///
|
||||
/// For LTR, the default alignment is on the left.
|
||||
/// For RTL, the default alignment is on the right.
|
||||
bool _usesDefaultAlignment = true;
|
||||
|
||||
ValueNotifier<bool> get _selectionOnTapEnabled =>
|
||||
WidgetsBinding.instance.debugWidgetInspectorSelectionOnTapEnabled;
|
||||
@ -3749,7 +3753,11 @@ class _WidgetInspectorButtonGroupState extends State<_WidgetInspectorButtonGroup
|
||||
return null;
|
||||
}
|
||||
|
||||
final String buttonLabel = 'Move to the ${_leftAligned ? 'right' : 'left'}';
|
||||
final TextDirection textDirection = Directionality.of(context);
|
||||
|
||||
final String buttonLabel =
|
||||
'Move to the ${_usesDefaultAlignment == (textDirection == TextDirection.ltr) ? 'right' : 'left'}';
|
||||
|
||||
return _WidgetInspectorButton(
|
||||
button: buttonBuilder(
|
||||
context,
|
||||
@ -3758,7 +3766,7 @@ class _WidgetInspectorButtonGroupState extends State<_WidgetInspectorButtonGroup
|
||||
_onTooltipHidden();
|
||||
},
|
||||
semanticsLabel: buttonLabel,
|
||||
isLeftAligned: _leftAligned,
|
||||
usesDefaultAlignment: _usesDefaultAlignment,
|
||||
),
|
||||
onTooltipVisible: () {
|
||||
_changeTooltipMessage(buttonLabel);
|
||||
@ -3819,24 +3827,25 @@ class _WidgetInspectorButtonGroupState extends State<_WidgetInspectorButtonGroup
|
||||
painter: _ExitWidgetSelectionTooltipPainter(
|
||||
tooltipMessage: _tooltipMessage,
|
||||
buttonKey: _exitWidgetSelectionButtonKey,
|
||||
isLeftAligned: _leftAligned,
|
||||
usesDefaultAlignment: _usesDefaultAlignment,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
if (_leftAligned) selectionModeButtons,
|
||||
if (_usesDefaultAlignment) selectionModeButtons,
|
||||
if (_moveExitWidgetSelectionButton != null) _moveExitWidgetSelectionButton!,
|
||||
if (!_leftAligned) selectionModeButtons,
|
||||
if (!_usesDefaultAlignment) selectionModeButtons,
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
return Positioned(
|
||||
left: _leftAligned ? _kExitWidgetSelectionButtonMargin : null,
|
||||
right: _leftAligned ? null : _kExitWidgetSelectionButtonMargin,
|
||||
return Positioned.directional(
|
||||
textDirection: Directionality.of(context),
|
||||
start: _usesDefaultAlignment ? _kExitWidgetSelectionButtonMargin : null,
|
||||
end: _usesDefaultAlignment ? null : _kExitWidgetSelectionButtonMargin,
|
||||
bottom: _kExitWidgetSelectionButtonMargin,
|
||||
child: buttonGroup,
|
||||
);
|
||||
@ -3868,7 +3877,7 @@ class _WidgetInspectorButtonGroupState extends State<_WidgetInspectorButtonGroup
|
||||
void _changeButtonGroupAlignment() {
|
||||
if (mounted) {
|
||||
setState(() {
|
||||
_leftAligned = !_leftAligned;
|
||||
_usesDefaultAlignment = !_usesDefaultAlignment;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -3974,12 +3983,12 @@ class _ExitWidgetSelectionTooltipPainter extends CustomPainter {
|
||||
_ExitWidgetSelectionTooltipPainter({
|
||||
required this.tooltipMessage,
|
||||
required this.buttonKey,
|
||||
required this.isLeftAligned,
|
||||
required this.usesDefaultAlignment,
|
||||
});
|
||||
|
||||
final String? tooltipMessage;
|
||||
final GlobalKey buttonKey;
|
||||
final bool isLeftAligned;
|
||||
final bool usesDefaultAlignment;
|
||||
|
||||
@override
|
||||
void paint(Canvas canvas, Size size) {
|
||||
@ -4021,7 +4030,7 @@ class _ExitWidgetSelectionTooltipPainter extends CustomPainter {
|
||||
final double tooltipHeight = textHeight + (tooltipPadding * 2);
|
||||
|
||||
final double tooltipXOffset =
|
||||
isLeftAligned ? 0 - buttonWidth : 0 - (tooltipWidth - buttonWidth);
|
||||
usesDefaultAlignment ? 0 - buttonWidth : 0 - (tooltipWidth - buttonWidth);
|
||||
final double tooltipYOffset = 0 - tooltipHeight - tooltipSpacing;
|
||||
|
||||
// Draw tooltip background.
|
||||
|
||||
@ -996,11 +996,9 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'WidgetInspector Move Exit Selection Mode button to the right / left',
|
||||
'[LTR] WidgetInspector Move Exit Selection Mode button to the right then left',
|
||||
(WidgetTester tester) async {
|
||||
// Enable widget selection mode.
|
||||
WidgetInspectorService.instance.isSelectMode = true;
|
||||
|
||||
final GlobalKey inspectorKey = GlobalKey();
|
||||
setupDefaultPubRootDirectory(service);
|
||||
|
||||
@ -1023,12 +1021,12 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
|
||||
BuildContext context, {
|
||||
required VoidCallback onPressed,
|
||||
required String semanticsLabel,
|
||||
bool isLeftAligned = true,
|
||||
bool usesDefaultAlignment = true,
|
||||
}) {
|
||||
return Material(
|
||||
child: ElevatedButton(
|
||||
onPressed: onPressed,
|
||||
child: Text(isLeftAligned ? 'MOVE RIGHT' : 'MOVE LEFT'),
|
||||
child: Text(usesDefaultAlignment ? 'MOVE RIGHT' : 'MOVE LEFT'),
|
||||
),
|
||||
);
|
||||
}
|
||||
@ -1050,33 +1048,104 @@ class _TestWidgetInspectorService extends TestWidgetInspectorService {
|
||||
),
|
||||
);
|
||||
|
||||
// Initially the exit select button is on the left.
|
||||
final Finder exitButton = buttonFinder('EXIT SELECT MODE');
|
||||
expect(exitButton, findsOneWidget);
|
||||
final Finder moveRightButton = buttonFinder('MOVE RIGHT');
|
||||
expect(moveRightButton, findsOneWidget);
|
||||
final double initialExitButtonX = tester.getCenter(exitButton).dx;
|
||||
|
||||
// Move the button to the right.
|
||||
await tester.tap(moveRightButton);
|
||||
await tester.pump();
|
||||
|
||||
// Verify the button is now on the right.
|
||||
expect(moveRightButton, findsNothing);
|
||||
final Finder moveLeftButton = buttonFinder('MOVE LEFT');
|
||||
expect(moveLeftButton, findsOneWidget);
|
||||
final double exitButtonXAfterMovingRight = tester.getCenter(exitButton).dx;
|
||||
expect(initialExitButtonX, lessThan(exitButtonXAfterMovingRight));
|
||||
final double movedExitButtonX = tester.getCenter(exitButton).dx;
|
||||
|
||||
expect(initialExitButtonX, lessThan(movedExitButtonX), reason: 'LTR: should move right');
|
||||
|
||||
// Move the button to the left again.
|
||||
await tester.tap(moveLeftButton);
|
||||
await tester.pump();
|
||||
|
||||
// Verify the button is in its original position.
|
||||
expect(moveLeftButton, findsNothing);
|
||||
final double finalExitButtonX = tester.getCenter(exitButton).dx;
|
||||
expect(finalExitButtonX, equals(initialExitButtonX));
|
||||
},
|
||||
// [intended] Test requires --track-widget-creation flag.
|
||||
skip: !WidgetInspectorService.instance.isWidgetCreationTracked(),
|
||||
);
|
||||
|
||||
testWidgets(
|
||||
'[RTL] WidgetInspector Move Exit Selection Mode button to the left then right',
|
||||
(WidgetTester tester) async {
|
||||
WidgetInspectorService.instance.isSelectMode = true;
|
||||
final GlobalKey inspectorKey = GlobalKey();
|
||||
setupDefaultPubRootDirectory(service);
|
||||
|
||||
Widget exitWidgetSelectionButtonBuilder(
|
||||
BuildContext context, {
|
||||
required VoidCallback onPressed,
|
||||
required String semanticsLabel,
|
||||
required GlobalKey key,
|
||||
}) {
|
||||
return Material(
|
||||
child: ElevatedButton(
|
||||
onPressed: onPressed,
|
||||
key: key,
|
||||
child: const Text('EXIT SELECT MODE'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget moveWidgetSelectionButtonBuilder(
|
||||
BuildContext context, {
|
||||
required VoidCallback onPressed,
|
||||
required String semanticsLabel,
|
||||
bool usesDefaultAlignment = true,
|
||||
}) {
|
||||
return Material(
|
||||
child: ElevatedButton(
|
||||
onPressed: onPressed,
|
||||
child: Text(usesDefaultAlignment ? 'MOVE RIGHT' : 'MOVE LEFT'),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Finder buttonFinder(String buttonText) {
|
||||
return find.ancestor(of: find.text(buttonText), matching: find.byType(ElevatedButton));
|
||||
}
|
||||
|
||||
await tester.pumpWidget(
|
||||
Directionality(
|
||||
textDirection: TextDirection.rtl,
|
||||
child: WidgetInspector(
|
||||
key: inspectorKey,
|
||||
exitWidgetSelectionButtonBuilder: exitWidgetSelectionButtonBuilder,
|
||||
moveExitWidgetSelectionButtonBuilder: moveWidgetSelectionButtonBuilder,
|
||||
tapBehaviorButtonBuilder: null,
|
||||
child: const Text('APP'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final Finder exitButton = buttonFinder('EXIT SELECT MODE');
|
||||
expect(exitButton, findsOneWidget);
|
||||
final Finder moveRightButton = buttonFinder('MOVE RIGHT');
|
||||
expect(moveRightButton, findsOneWidget);
|
||||
final double exitButtonXAfterMovingLeft = tester.getCenter(exitButton).dx;
|
||||
expect(exitButtonXAfterMovingLeft, equals(initialExitButtonX));
|
||||
final double initialExitButtonX = tester.getCenter(exitButton).dx;
|
||||
|
||||
await tester.tap(moveRightButton);
|
||||
await tester.pump();
|
||||
|
||||
final Finder moveLeftButton = buttonFinder('MOVE LEFT');
|
||||
expect(moveLeftButton, findsOneWidget);
|
||||
final double movedExitButtonX = tester.getCenter(exitButton).dx;
|
||||
|
||||
expect(initialExitButtonX, greaterThan(movedExitButtonX), reason: 'RTL: should move left');
|
||||
|
||||
await tester.tap(moveLeftButton);
|
||||
await tester.pump();
|
||||
|
||||
final double finalExitButtonX = tester.getCenter(exitButton).dx;
|
||||
expect(finalExitButtonX, equals(initialExitButtonX));
|
||||
},
|
||||
// [intended] Test requires --track-widget-creation flag.
|
||||
skip: !WidgetInspectorService.instance.isWidgetCreationTracked(),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user