mirror of
https://github.com/flutter/flutter.git
synced 2026-02-20 02:29:02 +08:00
Merge pull request #1822 from abarth/custom_shifted_box
Add CustomOneChildLayout
This commit is contained in:
commit
7ae730bb2e
@ -205,6 +205,71 @@ class RenderPositionedBox extends RenderShiftedBox {
|
||||
String debugDescribeSettings(String prefix) => '${super.debugDescribeSettings(prefix)}${prefix}alignment: $alignment\n';
|
||||
}
|
||||
|
||||
/// A delegate for computing the layout of a render object with a single child.
|
||||
class OneChildLayoutDelegate {
|
||||
/// Returns the size of this object given the incomming constraints.
|
||||
Size getSize(BoxConstraints constraints) => constraints.biggest;
|
||||
|
||||
/// Returns the box constraints for the child given the incomming constraints.
|
||||
BoxConstraints getConstraintsForChild(BoxConstraints constraints) => constraints;
|
||||
|
||||
/// Returns the position where the child should be placed given the size of this object and the size of the child.
|
||||
Point getPositionForChild(Size size, Size childSize) => Point.origin;
|
||||
}
|
||||
|
||||
class RenderCustomOneChildLayoutBox extends RenderShiftedBox {
|
||||
RenderCustomOneChildLayoutBox({
|
||||
RenderBox child,
|
||||
OneChildLayoutDelegate delegate
|
||||
}) : _delegate = delegate, super(child) {
|
||||
assert(delegate != null);
|
||||
}
|
||||
|
||||
OneChildLayoutDelegate get delegate => _delegate;
|
||||
OneChildLayoutDelegate _delegate;
|
||||
void set delegate (OneChildLayoutDelegate newDelegate) {
|
||||
assert(newDelegate != null);
|
||||
if (_delegate == newDelegate)
|
||||
return;
|
||||
_delegate = newDelegate;
|
||||
markNeedsLayout();
|
||||
}
|
||||
|
||||
Size _getSize(BoxConstraints constraints) {
|
||||
return constraints.constrain(_delegate.getSize(constraints));
|
||||
}
|
||||
|
||||
double getMinIntrinsicWidth(BoxConstraints constraints) {
|
||||
return _getSize(constraints).width;
|
||||
}
|
||||
|
||||
double getMaxIntrinsicWidth(BoxConstraints constraints) {
|
||||
return _getSize(constraints).width;
|
||||
}
|
||||
|
||||
double getMinIntrinsicHeight(BoxConstraints constraints) {
|
||||
return _getSize(constraints).height;
|
||||
}
|
||||
|
||||
double getMaxIntrinsicHeight(BoxConstraints constraints) {
|
||||
return _getSize(constraints).height;
|
||||
}
|
||||
|
||||
bool get sizedByParent => true;
|
||||
|
||||
void performResize() {
|
||||
size = _getSize(constraints);
|
||||
}
|
||||
|
||||
void performLayout() {
|
||||
if (child != null) {
|
||||
child.layout(delegate.getConstraintsForChild(constraints), parentUsesSize: true);
|
||||
final BoxParentData childParentData = child.parentData;
|
||||
childParentData.position = delegate.getPositionForChild(size, child.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class RenderBaseline extends RenderShiftedBox {
|
||||
|
||||
RenderBaseline({
|
||||
|
||||
@ -35,6 +35,7 @@ export 'package:flutter/rendering.dart' show
|
||||
LinearGradient,
|
||||
Matrix4,
|
||||
Offset,
|
||||
OneChildLayoutDelegate,
|
||||
Paint,
|
||||
Path,
|
||||
PlainTextSpan,
|
||||
@ -140,13 +141,21 @@ class CustomPaint extends OneChildRenderObjectWidget {
|
||||
assert(onPaint != null);
|
||||
}
|
||||
|
||||
/// This widget repaints whenver you supply a new onPaint callback.
|
||||
///
|
||||
/// If you use an anonymous closure for the onPaint callback, you'll trigger
|
||||
/// a repaint every time you build this widget, which might not be what you
|
||||
/// intend. Instead, consider passing a reference to a member function, which
|
||||
/// has a more stable identity.
|
||||
final CustomPaintCallback onPaint;
|
||||
final Object token; // set this to be repainted automatically when the token changes
|
||||
|
||||
/// This widget repaints whenever you supply a new token.
|
||||
final Object token;
|
||||
|
||||
RenderCustomPaint createRenderObject() => new RenderCustomPaint(onPaint: onPaint);
|
||||
|
||||
void updateRenderObject(RenderCustomPaint renderObject, CustomPaint oldWidget) {
|
||||
if (oldWidget != null && oldWidget.token != token)
|
||||
if (oldWidget.token != token)
|
||||
renderObject.markNeedsPaint();
|
||||
renderObject.onPaint = onPaint;
|
||||
}
|
||||
@ -244,6 +253,35 @@ class Center extends Align {
|
||||
: super(key: key, shrinkWrap: shrinkWrap, child: child);
|
||||
}
|
||||
|
||||
class CustomOneChildLayout extends OneChildRenderObjectWidget {
|
||||
CustomOneChildLayout({
|
||||
Key key,
|
||||
this.delegate,
|
||||
this.token,
|
||||
Widget child
|
||||
}) : super(key: key, child: child) {
|
||||
assert(delegate != null);
|
||||
}
|
||||
|
||||
/// A long-lived delegate that controls the layout of this widget.
|
||||
///
|
||||
/// Whenever the delegate changes, we need to recompute the layout of this
|
||||
/// widget, which means you might not want to create a new delegate instance
|
||||
/// every time you build this widget. Instead, consider using a long-lived
|
||||
/// deletate (perhaps held in a component's state) that you re-use every time
|
||||
/// you build this widget.
|
||||
final OneChildLayoutDelegate delegate;
|
||||
final Object token;
|
||||
|
||||
RenderCustomOneChildLayoutBox createRenderObject() => new RenderCustomOneChildLayoutBox(delegate: delegate);
|
||||
|
||||
void updateRenderObject(RenderCustomOneChildLayoutBox renderObject, CustomOneChildLayout oldWidget) {
|
||||
if (oldWidget.token != token)
|
||||
renderObject.markNeedsLayout();
|
||||
renderObject.delegate = delegate;
|
||||
}
|
||||
}
|
||||
|
||||
class SizedBox extends OneChildRenderObjectWidget {
|
||||
SizedBox({ Key key, this.width, this.height, Widget child })
|
||||
: super(key: key, child: child);
|
||||
|
||||
59
packages/unit/test/widget/custom_one_child_layout_test.dart
Normal file
59
packages/unit/test/widget/custom_one_child_layout_test.dart
Normal file
@ -0,0 +1,59 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:test/test.dart';
|
||||
|
||||
import 'widget_tester.dart';
|
||||
|
||||
class TestOneChildLayoutDelegate extends OneChildLayoutDelegate {
|
||||
BoxConstraints constraintsFromGetSize;
|
||||
BoxConstraints constraintsFromGetConstraintsForChild;
|
||||
Size sizeFromGetPositionForChild;
|
||||
Size childSizeFromGetPositionForChild;
|
||||
|
||||
Size getSize(BoxConstraints constraints) {
|
||||
constraintsFromGetSize = constraints;
|
||||
return new Size(200.0, 300.0);
|
||||
}
|
||||
|
||||
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
|
||||
constraintsFromGetConstraintsForChild = constraints;
|
||||
return new BoxConstraints(
|
||||
minWidth: 100.0,
|
||||
maxWidth: 150.0,
|
||||
minHeight: 200.0,
|
||||
maxHeight: 400.0
|
||||
);
|
||||
}
|
||||
|
||||
Point getPositionForChild(Size size, Size childSize) {
|
||||
sizeFromGetPositionForChild = size;
|
||||
childSizeFromGetPositionForChild = childSize;
|
||||
return Point.origin;
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
test('Control test for CustomOneChildLayout', () {
|
||||
testWidgets((WidgetTester tester) {
|
||||
TestOneChildLayoutDelegate delegate = new TestOneChildLayoutDelegate();
|
||||
tester.pumpWidget(new Center(
|
||||
child: new CustomOneChildLayout(delegate: delegate, child: new Container())
|
||||
));
|
||||
|
||||
expect(delegate.constraintsFromGetSize.minWidth, 0.0);
|
||||
expect(delegate.constraintsFromGetSize.maxWidth, 800.0);
|
||||
expect(delegate.constraintsFromGetSize.minHeight, 0.0);
|
||||
expect(delegate.constraintsFromGetSize.maxHeight, 600.0);
|
||||
|
||||
expect(delegate.constraintsFromGetConstraintsForChild.minWidth, 0.0);
|
||||
expect(delegate.constraintsFromGetConstraintsForChild.maxWidth, 800.0);
|
||||
expect(delegate.constraintsFromGetConstraintsForChild.minHeight, 0.0);
|
||||
expect(delegate.constraintsFromGetConstraintsForChild.maxHeight, 600.0);
|
||||
|
||||
expect(delegate.sizeFromGetPositionForChild.width, 200.0);
|
||||
expect(delegate.sizeFromGetPositionForChild.height, 300.0);
|
||||
|
||||
expect(delegate.childSizeFromGetPositionForChild.width, 150.0);
|
||||
expect(delegate.childSizeFromGetPositionForChild.height, 400.0);
|
||||
});
|
||||
});
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user