Merge pull request #1446 from Hixie/fractionally_sized_box
FractionallySizedBox
This commit is contained in:
commit
dd6790fc60
@ -145,6 +145,98 @@ class RenderConstrainedBox extends RenderProxyBox {
|
|||||||
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}additionalConstraints: ${additionalConstraints}\n';
|
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}additionalConstraints: ${additionalConstraints}\n';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A render object that, for both width and height, imposes a tight constraint
|
||||||
|
/// on its child that is a multiple (typically less than 1.0) of the maximum
|
||||||
|
/// constraint it received from its parent on that axis. If the factor for a
|
||||||
|
/// given axis is null, then the constraints from the parent are just passed
|
||||||
|
/// through instead.
|
||||||
|
///
|
||||||
|
/// It then tries to size itself the size of its child.
|
||||||
|
class RenderFractionallySizedBox extends RenderProxyBox {
|
||||||
|
RenderFractionallySizedBox({
|
||||||
|
RenderBox child,
|
||||||
|
double widthFactor,
|
||||||
|
double heightFactor
|
||||||
|
}) : _widthFactor = widthFactor, _heightFactor = heightFactor, super(child) {
|
||||||
|
assert(_widthFactor == null || _widthFactor > 0.0);
|
||||||
|
assert(_heightFactor == null || _heightFactor > 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The multiple to apply to the incoming maximum width constraint to use as
|
||||||
|
/// the tight width constraint for the child, or null to pass through the
|
||||||
|
/// constraints given by the parent.
|
||||||
|
double get widthFactor => _widthFactor;
|
||||||
|
double _widthFactor;
|
||||||
|
void set widthFactor (double value) {
|
||||||
|
assert(value == null || value > 0.0);
|
||||||
|
if (_widthFactor == value)
|
||||||
|
return;
|
||||||
|
_widthFactor = value;
|
||||||
|
markNeedsLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The multiple to apply to the incoming maximum height constraint to use as
|
||||||
|
/// the tight height constraint for the child, or null to pass through the
|
||||||
|
/// constraints given by the parent.
|
||||||
|
double get heightFactor => _heightFactor;
|
||||||
|
double _heightFactor;
|
||||||
|
void set heightFactor (double value) {
|
||||||
|
assert(value == null || value > 0.0);
|
||||||
|
if (_heightFactor == value)
|
||||||
|
return;
|
||||||
|
_heightFactor = value;
|
||||||
|
markNeedsLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
BoxConstraints _computeChildConstraints(BoxConstraints constraints) {
|
||||||
|
return new BoxConstraints(
|
||||||
|
minWidth: _widthFactor == null ? constraints.minWidth : constraints.maxWidth * _widthFactor,
|
||||||
|
maxWidth: _widthFactor == null ? constraints.maxWidth : constraints.maxWidth * _widthFactor,
|
||||||
|
minHeight: _heightFactor == null ? constraints.minHeight : constraints.maxHeight * _heightFactor,
|
||||||
|
maxHeight: _heightFactor == null ? constraints.maxHeight : constraints.maxHeight * _heightFactor
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
double getMinIntrinsicWidth(BoxConstraints constraints) {
|
||||||
|
if (child != null)
|
||||||
|
return child.getMinIntrinsicWidth(_computeChildConstraints(constraints));
|
||||||
|
return _computeChildConstraints(constraints).constrainWidth(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
double getMaxIntrinsicWidth(BoxConstraints constraints) {
|
||||||
|
if (child != null)
|
||||||
|
return child.getMaxIntrinsicWidth(_computeChildConstraints(constraints));
|
||||||
|
return _computeChildConstraints(constraints).constrainWidth(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
double getMinIntrinsicHeight(BoxConstraints constraints) {
|
||||||
|
if (child != null)
|
||||||
|
return child.getMinIntrinsicHeight(_computeChildConstraints(constraints));
|
||||||
|
return _computeChildConstraints(constraints).constrainHeight(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
double getMaxIntrinsicHeight(BoxConstraints constraints) {
|
||||||
|
if (child != null)
|
||||||
|
return child.getMaxIntrinsicHeight(_computeChildConstraints(constraints));
|
||||||
|
return _computeChildConstraints(constraints).constrainHeight(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void performLayout() {
|
||||||
|
if (child != null) {
|
||||||
|
child.layout(_computeChildConstraints(constraints), parentUsesSize: true);
|
||||||
|
size = child.size;
|
||||||
|
} else {
|
||||||
|
size = _computeChildConstraints(constraints).constrain(Size.zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String debugDescribeSettings(String prefix) {
|
||||||
|
return '${super.debugDescribeSettings(prefix)}' +
|
||||||
|
'${prefix}widthFactor: ${_widthFactor ?? "pass-through"}\n' +
|
||||||
|
'${prefix}heightFactor: ${_heightFactor ?? "pass-through"}\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A render object that imposes different constraints on its child than it gets
|
/// A render object that imposes different constraints on its child than it gets
|
||||||
/// from its parent, possibly allowing the child to overflow the parent.
|
/// from its parent, possibly allowing the child to overflow the parent.
|
||||||
///
|
///
|
||||||
|
@ -244,6 +244,24 @@ class ConstrainedBox extends OneChildRenderObjectWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FractionallySizedBox extends OneChildRenderObjectWidget {
|
||||||
|
FractionallySizedBox({ Key key, this.width, this.height, Widget child })
|
||||||
|
: super(key: key, child: child);
|
||||||
|
|
||||||
|
final double width;
|
||||||
|
final double height;
|
||||||
|
|
||||||
|
RenderFractionallySizedBox createRenderObject() => new RenderFractionallySizedBox(
|
||||||
|
widthFactor: width,
|
||||||
|
heightFactor: height
|
||||||
|
);
|
||||||
|
|
||||||
|
void updateRenderObject(RenderFractionallySizedBox renderObject, SizedBox oldWidget) {
|
||||||
|
renderObject.widthFactor = width;
|
||||||
|
renderObject.heightFactor = height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class OverflowBox extends OneChildRenderObjectWidget {
|
class OverflowBox extends OneChildRenderObjectWidget {
|
||||||
OverflowBox({ Key key, this.minWidth, this.maxWidth, this.minHeight, this.maxHeight, Widget child })
|
OverflowBox({ Key key, this.minWidth, this.maxWidth, this.minHeight, this.maxHeight, Widget child })
|
||||||
: super(key: key, child: child);
|
: super(key: key, child: child);
|
||||||
|
35
packages/unit/test/widget/fractionally_sized_box_test.dart
Normal file
35
packages/unit/test/widget/fractionally_sized_box_test.dart
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
import 'package:sky/widgets.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
import 'widget_tester.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
test('FractionallySizedBox', () {
|
||||||
|
testWidgets((WidgetTester tester) {
|
||||||
|
Size detectedSize;
|
||||||
|
GlobalKey inner = new GlobalKey();
|
||||||
|
tester.pumpWidget(new OverflowBox(
|
||||||
|
minWidth: 0.0,
|
||||||
|
maxWidth: 100.0,
|
||||||
|
minHeight: 0.0,
|
||||||
|
maxHeight: 100.0,
|
||||||
|
child: new Center(
|
||||||
|
child: new FractionallySizedBox(
|
||||||
|
width: 0.5,
|
||||||
|
height: 0.25,
|
||||||
|
child: new SizeObserver(
|
||||||
|
callback: (Size size) {
|
||||||
|
detectedSize = size;
|
||||||
|
},
|
||||||
|
child: new Container(
|
||||||
|
key: inner
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
));
|
||||||
|
expect(detectedSize, equals(const Size(50.0, 25.0)));
|
||||||
|
expect(inner.currentContext.findRenderObject().localToGlobal(Point.origin), equals(const Point(25.0, 37.5)));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user