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
Shift
key is pressed. - ResizeMode.symmetric: When
Alt
orOption
key is pressed. - ResizeMode.symmetricScale: When both
Shift
andAlt
/Option
keys 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) {...},
);