Resizing
TransformableBox is used to resize its content by default. Transformable Box utilizes
Box Transform to create a fully-featured Flutter implementation of the Box Transform API.
Stack(
children: [
TransformableBox(
rect: rect,
flip: flip,
onChanged: (event) {
setState(() {
this.rect = event.rect;
this.flip = event.flip;
});
},
contentBuilder: (context, rect, flip) => Image.asset( // your widget goes here.
'assets/images/landscape.jpg',
width: rect.width,
height: rect.height,
fit: BoxFit.fill,
),
),
],
);
By default, resizing allows flipping the rect horizontally and vertically. Flipping is done by using the
Transform.scale widget with negative scale values.
Resizing is freeform by default, meaning that the user can resize the box in any direction and in any size.
Controlling Resize Modes
The resizeModeResolver is a callback that is called whenever a resize operation is about to be performed on a
given Transformable Box. This allows you to define the resize behavior at the time of the resize
operation. This is useful when you want to change the resize behavior based on the state of the application.
The most common use case for this is keyboard shortcuts. A defaultResizeModeResolver function is used by
default when resizing, and it's job is to listen to keyboard meta keys to change the ResizeMode.
Default Resize Mode:
- ResizeMode.freeform: Default mode. When no keys are pressed.
- ResizeMode.scale: When
Shiftkey is pressed. - ResizeMode.symmetric: When
AltorOptionkey is pressed. - ResizeMode.symmetricScale: When both
ShiftandAlt/Optionkeys are pressed.
See ResizeModes page for more information on the different resize modes.
Override this default behavior by providing resizeModeResolver in TransformableBox constructor to customize
resizing to your liking. This can also be used to allow only certain resize modes.
TransformableBox(
rect: rect,
flip: flip,
resizeModeResolver: () => ResizeMode.scale,
onChanged: (event) {...},
contentBuilder: (context, rect, flip) {...},
);
This will resize the box such that the aspect ratio is preserved at all times.
Flipping
By default, resizing allows flipping the rect horizontally and vertically. Flipping is done by using the
Transform.scale widget with negative scale values internally. There are two kinds of flipping involved in resizing:
Flipping the rect while resizing
While resizing, the rect can be flipped horizontally and vertically whenever the user drags a handle beyond the opposite side of the rect. This allows more freedom when resizing a box. However, this is not responsible for flipping the content of the box.
This behavior can be disabled by setting flipRectWhileResizing to false.
TransformableBox(
rect: rect,
flip: flip,
flipRectWhileResizing: false,
onChanged: (event) {...},
contentBuilder: (context, rect, flip) {...},
);
Flipping the content of the box
This is done by using the Transform.scale widget with negative scale values. This is done to allow the content to be
flipped horizontally and vertically.
This behavior can be disabled by setting allowContentFlipping to false.
TransformableBox(
rect: rect,
flip: flip,
allowContentFlipping: false,
onChanged: (event) {...},
contentBuilder: (context, rect, flip) {...},
);
You can set both flipRectWhileResizing and allowContentFlipping to false to disable flipping completely.
The result will be a box that stops shrinking once it reaches a size of zero, as if it hit a wall.
Constraints
Resizing can be constrained by providing any desirable combination of minHeight, minWidth, maxHeight and
maxWidth using the constraints property.
TransformableBox(
rect: rect,
flip: flip,
constraints: BoxConstraints(
minWidth: 100,
minHeight: 100,
maxWidth: 500,
maxHeight: 500,
),
onChanged: (event) {...},
contentBuilder: (context, rect, flip) {...},
);
This will disallow the box from growing or shrinking beyond 100x100 and 500x500 pixels.
Constraint callbacks
You can listen to callbacks to listen to when the box reaches the minimum or maximum size. This is useful when you want to react to these events to show some UI indication like showing a message or changing border color.
You can listen to the onTerminalSizeReached callback to listen to when the box reaches some terminal size, vertically
or horizontally to a minimum or maximum size. This is useful when you want to show a message to the user that the box
has reached some resizing limit.
clampingRect size.There are more granular terminal callback functions if desired. You can use onMinWidthReached, onMaxWidthReached,
onMinHeightReached and onMaxHeightReached callbacks to listen to the individual terminal size events.
You can also use onTerminalWidthReached and onTerminalHeightReached to listen to combined terminal width and height
events respectively.
TransformableBox(
rect: rect,
flip: flip,
constraints: BoxConstraints(
minWidth: 100,
minHeight: 100,
maxWidth: 500,
maxHeight: 500,
),
onTerminalSizeReached: (
bool reachedMinWidth,
bool reachedMaxWidth,
bool reachedMinHeight,
bool reachedMaxHeight,
) {
// do something here.
},
onChanged: (event) {...},
contentBuilder: (context, rect, flip) {...},
);
Handle visibility
Resizing can be disabled completely by setting the resizable property to false.
TransformableBox(
rect: rect,
flip: flip,
resizable: false,
onChanged: (event) {...},
contentBuilder: (context, rect, flip) {...},
);
You can alternatively selectively hide handles by providing your own visibleHandles set.
TransformableBox(
rect: rect,
flip: flip,
visibleHandles: {HandlePosition.right, HandlePosition.bottom, HandlePosition.bottomRight},
onChanged: (event) {...},
contentBuilder: (context, rect, flip) {...},
);
Handle Interaction
You can selectively disable handles but keep them visible at the same time by providing your own enabledHandles set.
TransformableBox(
rect: rect,
flip: flip,
enabledHandles: {HandlePosition.right, HandlePosition.bottom, HandlePosition.bottomRight},
onChanged: (event) {...},
contentBuilder: (context, rect, flip) {...},
);

