-
Notifications
You must be signed in to change notification settings - Fork 29k
Added OverflowBar widget #62350
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
Added OverflowBar widget #62350
Conversation
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
/// color: Colors.white, | ||
/// elevation: 24, | ||
/// shape: RoundedRectangleBorder( | ||
/// borderRadius: BorderRadius.all(Radius.circular(4.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.
Nit: Demo code should either consistently use or omit the .0
on doubles
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.
👍
/// [OverflowBarAlignment.start], and with the left edge of the | ||
/// available space for [OverflowBarAlignment.end]. For | ||
/// [OverflowBarAlignment.center] each child is horizontally | ||
/// centered with the available space. |
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.
/// centered with the available space. | |
/// centered within the available space. |
maybe?
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.
👍
/// of the children within the vertical "overflow" layout. | ||
final VerticalDirection overflowDirection; | ||
|
||
/// Determines the order that the [children] appear in for the default |
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.
If this is null, then it uses the inherited text direction right? Probably worth mentioning that in the documentation.
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.
👍
void debugFillProperties(DiagnosticPropertiesBuilder properties) { | ||
super.debugFillProperties(properties); | ||
properties.add(DoubleProperty('spacing', spacing, defaultValue: 0)); | ||
properties.add(DoubleProperty('overflowSpacing', overflowSpacing)); |
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.
To match the other lines
properties.add(DoubleProperty('overflowSpacing', overflowSpacing)); | |
properties.add(DoubleProperty('overflowSpacing', overflowSpacing, defaultValue: 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.
👍
child = childAfter(child); | ||
} | ||
|
||
final bool rtl = textDirection == TextDirection.rtl; |
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.
Nit:
final bool rtl = textDirection == TextDirection.rtl; | |
final bool isRtl = textDirection == TextDirection.rtl; |
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.
I had it this way originally but I suffer from a personal loathing for logically capitalizing acronyms, so rtl
.
} else { | ||
// Default horizontal layout | ||
child = rtl ? lastChild : firstChild; | ||
RenderBox nextChild() => textDirection == TextDirection.rtl ? childBefore(child) : childAfter(child); |
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.
RenderBox nextChild() => textDirection == TextDirection.rtl ? childBefore(child) : childAfter(child); | |
RenderBox nextChild() => rtl ? childBefore(child) : childAfter(child); |
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.
👍
expect(bar.children, const <Widget>[]); | ||
}); | ||
|
||
testWidgets('EmptyOverflowBar', (WidgetTester tester) async { |
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.
Nit/Suggestion:
testWidgets('EmptyOverflowBar', (WidgetTester tester) async { | |
testWidgets('Empty OverflowBar', (WidgetTester tester) async { |
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.
👍
// Children are vertically centered, start at x=0 | ||
await tester.pumpWidget(buildFrame(spacing: 10, textDirection: TextDirection.ltr)); | ||
expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(0, 8, 48, 56)); | ||
expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(10.0 + 48, 0, 10.0 + 112, 64)); |
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.
Nit: Should probably be consistent with keeping/omitting the .0
for doubles.
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.
I find that omitting the .0
makes code easier to read however it was necessary to introduce one in these expressions so that they eval to doubles instead of ints. I realize that it's inconsistent but I've tried to be consistent about that.
expect(tester.getRect(find.byKey(child1Key)), const Rect.fromLTRB(100.0/2.0 - 48/2, 0, 100.0/2.0 + 48/2, 48)); | ||
expect(tester.getRect(find.byKey(child2Key)), const Rect.fromLTRB(100.0/2.0 - 64/2, 48, 100.0/2.0 + 64/2, 112)); | ||
expect(tester.getRect(find.byKey(child3Key)), const Rect.fromLTRB(100.0/2.0 - 32/2, 112, 100.0/2.0 + 32/2, 144)); | ||
|
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.
Nit: Unnecessary new line
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.
👍
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.
Nice! LGTM, just a question about defaults.
/// used instead. | ||
/// | ||
/// Defaults to 0.0. | ||
final double spacing; |
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.
I wonder if we should make this default match the material spec for button spacing? Or is that assuming too much? It would just be nice to just wrap an array of buttons with an OverflowBar
with no params and have it match the old ButtonBar
layout by default.
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.
For a dialog you'd also need to end-align the OverflowBar and somewhere you need to ensure that the OverflowBar can be scrolled into view.
Using 0 for the spacing seemed appropriate for the widgets library since it's probably the wrong place to have an opinion about spacing.
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.
Ah, I missed that it was part of the widgets library 😄. Totally makes sense for it to be there and that the default should be 0.
/// | ||
/// This example defines a simple approximation of a dialog | ||
/// layout, where the layout of the dialog's action buttons are | ||
/// defined by an [OverflowBar]. The content is wrapped in a |
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.
nit: double space
/// layout, where the layout of the dialog's action buttons are | ||
/// defined by an [OverflowBar]. The content is wrapped in a | ||
/// [SingleChildScrollView], so that if overflow occurs, the | ||
/// action buttons will be still be accessible by scrolling, |
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.
... will be still be ... ?
class OverflowBar extends MultiChildRenderObjectWidget { | ||
/// Constructs an OverflowBar. | ||
/// | ||
/// The [spacing], [overflowSpacing], [overflowAlignment], |
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.
I believe children
of an MultiChildRenderObjectWidget
also cannot be null. Mention that in the docs and add an assert?
|
||
@override | ||
double computeMinIntrinsicHeight(double width) { | ||
RenderBox child = firstChild; |
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.
Is this calculation correct? I'd assumed that if width is big enough everything gets layed out in a row and then the hight would not be the sum of the children heights, no?
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.
Yes, you are correct, this method is incorrect. The min intrinsic height should be: if the sum of child intrinsic widths fit, then the max child height, otherwise the sum of the child heights.
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.
I've fixed this however I still need to add some tests for min/max intrinsic height.
This widget provides most of the same features as ButtonBar, without being tangled up with the Material ButtonTheme.
DartPad demo of OverflowBar: https://dartpad.dev/4791c69a962dd9da97b7b9748ac2983c