-
Notifications
You must be signed in to change notification settings - Fork 29.7k
Configurable padding for the CupertinoSegmentedControl #30807
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Configurable padding for the CupertinoSegmentedControl #30807
Conversation
|
Hi @vanlooverenkoen, thanks for your contribution! Could you add some tests for the changes you made? |
…lso the custom padding is set
|
I have added 2 tests
|
…-segmented-control
|
@LongCatIsLooong, is there something else I should do to get this PR merged? |
LongCatIsLooong
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry for taking so long.
| /// Defaults to the selectedColor at 20% opacity if null. | ||
| final Color pressedColor; | ||
|
|
||
| /// The [children], if any, are placed inside this padding. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's guaranteed a segmented control will have more than 1 child.
flutter/packages/flutter/lib/src/cupertino/segmented_control.dart
Lines 91 to 92 in 0de21c0
| }) : assert(children != null), | |
| assert(children.length >= 2), |
| ), | ||
| ); | ||
|
|
||
| expect(find.byType(Padding), findsOneWidget); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Inspecting Padding directly to see if the parameter is set correctly seems a bit implementation dependent, IMO it's better to verify the expected behavior.
I'd prefer to verify that the bounding Rect of child widgets is indeed inset by padding amount, i.e. verify the top left corner of "Child 1" is Offset(16, 0) to the top left corner of CupertinoSegmentedControl<int> etc..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How should I implement this test? coordinates_test.dart is what I am looking at at this point.
final RenderBox boxA = tester.renderObject(find.byKey(keyChild1));
expect(boxA.globalToLocal(Offset.zero), equals(const Offset(0.0, 286.0)));
How can I check what the position is between 2 widgets?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The WidgetTester class offers methods to get the key coordinates of a widget, e.g. getBottomLeft.
A good example would be this test:
flutter/packages/flutter/test/cupertino/segmented_control_test.dart
Lines 374 to 399 in 0de21c0
| testWidgets('Widgets are centered within segments', (WidgetTester tester) async { | |
| final Map<int, Widget> children = <int, Widget>{}; | |
| children[0] = const Text('Child 1'); | |
| children[1] = const Text('Child 2'); | |
| await tester.pumpWidget( | |
| Directionality( | |
| textDirection: TextDirection.ltr, | |
| child: Align( | |
| alignment: Alignment.topLeft, | |
| child: SizedBox( | |
| width: 200.0, | |
| height: 200.0, | |
| child: CupertinoSegmentedControl<int>( | |
| children: children, | |
| onValueChanged: (int newValue) { }, | |
| ), | |
| ), | |
| ), | |
| ), | |
| ); | |
| // Widgets are centered taking into account 16px of horizontal padding | |
| expect(tester.getCenter(find.text('Child 1')), const Offset(58.0, 100.0)); | |
| expect(tester.getCenter(find.text('Child 2')), const Offset(142.0, 100.0)); | |
| }); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
e.g.
testWidgets('Padding works', (WidgetTester tester) async {
const Key key = Key('Container');
final Map<int, Widget> children = <int, Widget>{};
children[0] = const SizedBox(
height: double.infinity,
child: Text('Child 1'),
) ;
children[1] = const SizedBox(
height: double.infinity,
child: Text('Child 2'),
) ;
Future<void> verifyPadding({ EdgeInsets padding }) async {
final EdgeInsets effectivePadding = padding ?? const EdgeInsets.symmetric(horizontal: 16);
final Rect segmentedControlRect = tester.getRect(find.byKey(key));
expect(
tester.getTopLeft(find.byWidget(children[0])),
segmentedControlRect.topLeft.translate(
effectivePadding.topLeft.dx,
effectivePadding.topLeft.dy,
)
);
expect(
tester.getBottomLeft(find.byWidget(children[0])),
segmentedControlRect.bottomLeft.translate(
effectivePadding.bottomLeft.dx,
effectivePadding.bottomLeft.dy,
),
);
expect(
tester.getTopRight(find.byWidget(children[1])),
segmentedControlRect.topRight.translate(
effectivePadding.topRight.dx,
effectivePadding.topRight.dy,
),
);
expect(
tester.getBottomRight(find.byWidget(children[1])),
segmentedControlRect.bottomRight.translate(
effectivePadding.bottomRight.dx,
effectivePadding.bottomRight.dy,
),
);
}
await tester.pumpWidget(
boilerplate(
child: CupertinoSegmentedControl<int>(
key: key,
children: children,
onValueChanged: (int newValue) { },
),
)
);
// Default padding works.
await verifyPadding();
// Switch to Child 2 padding should remain the same.
await tester.tap(find.text('Child 2'));
await tester.pumpAndSettle();
await verifyPadding();
await tester.pumpWidget(
boilerplate(
child: CupertinoSegmentedControl<int>(
key: key,
padding: const EdgeInsets.fromLTRB(1, 3, 5, 7),
children: children,
onValueChanged: (int newValue) { },
),
)
);
// Custom padding works.
await verifyPadding(padding: const EdgeInsets.fromLTRB(1, 3, 5, 7));
// Switch back to Child 1 padding should remain the same.
await tester.tap(find.text('Child 1'));
await tester.pumpAndSettle();
await verifyPadding(padding: const EdgeInsets.fromLTRB(1, 3, 5, 7));
});| ), | ||
| ); | ||
|
|
||
| expect(find.byType(Padding), findsOneWidget); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here too
| /// The [children], if any, are placed inside this padding. | ||
| /// | ||
| /// Defaults to EdgeInsets.symmetric(horizontal: 16.0) | ||
| final EdgeInsets padding; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's change this to EdgeInsetsGeometry. Otherwise this is specifying that we use left and right regardless of Directionality.
|
|
||
| return Padding( | ||
| padding: _kHorizontalItemPadding.resolve(Directionality.of(context)), | ||
| padding: widget.padding ?? _kHorizontalItemPadding.resolve(Directionality.of(context)), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once we change it to an EdgeInsetGeometry, we should remove the .resolve here.
|
@LongCatIsLooong How can I check what the position is between 2 widgets? |
|
@vanlooverenkoen I updated the comment with an example. |
…ed behavior instead of the implementation
LongCatIsLooong
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
| /// Defaults to the selectedColor at 20% opacity if null. | ||
| final Color pressedColor; | ||
|
|
||
| /// The CupertinoSegmentedControl will be placed inside this padding |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Copied from the docs of _kHorizontalItemPadding
| /// The CupertinoSegmentedControl will be placed inside this padding | |
| /// Minimum padding from edges of the segmented control to edges of encompassing | |
| /// widget. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry what I was talking about the padding property in CupertinoSegmentedControl. The padding is part of the CupertinoSegmentedControl widget but it sounded like it is not.
|
@vanlooverenkoen could you merge the current |
…-segmented-control
|
@LongCatIsLooong done |
|
😑 |
|
I cannot build anymore :( |
|
@vanlooverenkoen sorry for the inconvenience but could you rebase master and squash all your commits into one? Apparently if you merge the latest master into your branch the SDK version is still decided by the commit you branched off from master when you created this feature branch. |
…-segmented-control
|
😑 I do not understand what I am doing wrong |
|
My apologies for the inconvenience 😞, the versioning system in flutter SDK does not handle merge commits by design. Could you do a |
Added a configurable padding for the CupertinoSegmentedControl. The default of 16 will still be used if no padding was set.
#25989