NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
pub.dev · #1378 most downloaded on pub.dev
Widgets SideBySide, RowProportional, AnimatedBetween, Box, Pad, Delayed, WrapSuper, OtpCodeVerificationField, ButtonBarSuper, NormalizedOverflowBox, showDialogSuper and much more.
Last release 7 days ago
01 Oct 2026
Ships unpredictably
gaps range from 9 days to 1.1 years
Some releases are documented
notes for 29 of the last 60 stable releases
Nothing withdrawn
no release was ever pulled
7 years old
144 releases · first in 2019
New AnimatedBetween.onEnd callback.
New AnimatedBetween.onEnd callback.
SideBySide now supports CrossAxisAlignment.stretch and CrossAxisAlignment.baseline
(which requires the new textBaseline parameter, just like in a Row). Before, they
threw an UnimplementedError. When the available height is unbounded (for example,
inside a Column), stretch stretches all children to the height of the tallest one.
Breaking: Removed deprecated code:
Breaking: Migrate to the standalone material_ui and cupertino_ui packages.
Requires Flutter 3.44 / Dart 3.12 or newer. Applications using this package's
Material or Cupertino widgets should migrate their corresponding imports too,
so that themes, routes, and public UI types come from the same libraries.
Breaking: Removed deprecated code:
TextOneLine widget: Use Text with maxLines: 1, instead.SideBySide.startChild and SideBySide.endChild: Use the children property
instead.SideBySide.innerDistance: Use the gaps property instead.KeyboardDismiss widget: Use the Keyboard widget instead. Recommended:
Keyboard(iOsCloseOnTap: true, iOsCloseOnSwipe: true, iOsRemoveFocusOnTap: true, child: ...).KeyboardDismiss.keyboardDismiss(): Use Keyboard.close() instead.isScrolled (of DetectScroll): Use canScroll instead.Breaking: ButtonBarSuper is now a replacement for OverflowBar (which replaced
the deprecated ButtonBar), instead of for ButtonBar:
lineSpacing: Renamed to overflowSpacing, as in OverflowBar.buttonTextTheme, buttonMinWidth, buttonHeight, buttonPadding and
layoutBehavior: Removed, as OverflowBar doesn't have them. Style the buttons
themselves instead (for example, with ElevatedButton.styleFrom).ButtonBarTheme. Use spacing, overflowSpacing and a Padding widget instead.key parameter.One column per quarter.
New Keyboard.isOpening(context) and Keyboard.isClosing(context), to check whether the keyboard is currently moving up or down.
New Keyboard.isOpening(context) and Keyboard.isClosing(context), to check whether
the keyboard is currently moving up or down.
New Keyboard.openFraction(context), which returns how much the keyboard is open, from
0 (closed) to 1 (fully open). Widgets that call it rebuild on every frame while the
keyboard moves, so you can animate them together with the keyboard.
New KeyboardSwitch parameters opening and closing, shown while the keyboard is
moving up or down.
New KeyboardSwitch.fractionBuilder constructor, whose callback receives how much the
keyboard is open, and whether it's currently opening or closing.
New Keyboard params percentIsOpen and percentIsClosed (both default 0),
from 0 to 1, as a fraction of the height of the fully open keyboard. The
percentIsOpen controls when Keyboard.isOpen becomes true while the keyboard is
opening, and the percentIsClosed controls when Keyboard.isClosed becomes true while
it's closing. For example, percentIsOpen: 1 considers the keyboard open only when
it's fully open, and percentIsClosed: 1 considers it closed as soon as it starts
closing. The defaults keep the previous behavior: open as soon as it starts opening,
and closed only when it closes completely.
New AnimatedSymbol widget, which draws a plus, minus, times, check, equals or colon symbol, and animates smoothly between them when the symbol changes
New AnimatedSymbol widget, which draws a plus, minus, times, check, equals or colon
symbol, and animates smoothly between them when the symbol changes. You can choose the
thickness of the lines, the color, and the size of the widget.
New AnimatedSymbol widget, which draws a plus, minus, times, check, equals or colon symbol, and animates smoothly between them when the symbol changes
New AnimatedSymbol widget, which draws a plus, minus, times, check, equals or colon
symbol, and animates smoothly between them when the symbol changes. You can choose the
thickness of the lines, the color, and the size of the widget.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
New NoSpacesTextInputFormatter.trim() constructor. While the default NoSpacesTextInputFormatter() removes all whitespace, the trim one allows whitespa
NoSpacesTextInputFormatter.trim() constructor. While the default
NoSpacesTextInputFormatter() removes all whitespace, the trim one allows
whitespace but keeps it tidy while the user types: whitespace can never be the
first character of the text; line breaks are allowed, but at most one completely
blank line in a row; spaces and tabs are removed from the end of every line,
except from the last line (the one currently being typed); and double spaces are
not allowed (a run of spaces/tabs is reduced to a single space).New RowProportional parameter reservedPadding (default null): the fixed horizontal padding (left plus right) that each child has inside of it. Providi
New RowProportional parameter reservedPadding (default null): the fixed
horizontal padding (left plus right) that each child has inside of it. Providing it
(even with a value of zero) completely changes the way the available space is
divided between the children: the row then treats that padding as a fixed part of
each child, that never scales. If the available space is exactly the total of the
preferred widths of the children, they get exactly their preferred widths; if there
is more space, the extra space is divided equally between the children (and not
proportionally); and if there is less space, the paddings are kept and only the rest
of the children shrink, proportionally.
For example, two children with preferred widths of 60 and 100 (two texts of 30 and
70 pixels, each one with a horizontal padding of 15 pixels) with
reservedPadding: 30, get 60 and 100 pixels when the available space is 160; 480
and 520 pixels when it's 1000 (the 840 extra pixels are divided equally); and 42 and
58 pixels when it's 100 (60 pixels are kept for the paddings, and the other 40 are
divided between the texts, proportionally to 30 and 70).
When you don't provide the reservedPadding (the default), all the available space
is simply divided proportionally to the preferred widths, exactly as before.
Nothing published for this version
Nothing published for this version
The new SquircleBorder class is similar to Flutter's ContinuousRectangleBorder, but it allows more configuration options. It defines a rounded-rectang
The new SquircleBorder class is similar to Flutter's ContinuousRectangleBorder,
but it allows more configuration options. It defines a rounded-rectangle shape (like a
"squircle") where two things are chosen independently: how big the corners are,
and how the corner curve looks.
Nothing published for this version
New Keyboard parameter closeOnTapOnlyIfKeyboardIsOpen (default true). When true, the close-on-tap behavior (iOsCloseOnTap / androidCloseOnTap) acts on
Keyboard parameter closeOnTapOnlyIfKeyboardIsOpen (default true). When
true, the close-on-tap behavior (iOsCloseOnTap / androidCloseOnTap) acts only
when the system keyboard is actually open: while it's closed, tapping an empty area
of the screen does nothing.New TimeBuilder.each constructor, which rebuilds once for each given interval of time: TimeBuilder.each(interval: const Duration(seconds: 5), builder:
TimeBuilder.each constructor, which rebuilds once for each given interval of
time: TimeBuilder.each(interval: const Duration(seconds: 5), builder: ...) rebuilds
each 5 seconds. The ticks are aligned to the clock and never drift, so a 5 second
interval ticks when the clock reaches the seconds 0, 5, 10, 15 etc. The optional
numberOfTicks parameter stops the rebuilds after that number of ticks.New RowProportional widget, which arranges its children horizontally, dividing all the available horizontal space between them, proportionally to thei
New RowProportional widget, which arranges its children horizontally,
dividing all the available horizontal space between them, proportionally to
their preferred (natural, intrinsic) widths. Children are forced to their
calculated widths, so the row never overflows: with extra space the children
grow, and with less space they shrink, always keeping their relative
proportions. Wrapping a child in an Expanded multiplies its preferred width
by the flex, while a Flexible also allows the child to be smaller than its
calculated width. If one or more children are Spacers, there is no scaling
anymore: the other children get their preferred widths, and the leftover space
is divided between the spacers.
New FixedWidth widget, to be used as a direct child of RowProportional,
gives a child an immutable width that never scales and does not participate in
the proportional distribution of space. Use FixedWidth(width: 8) with no
child for a fixed 8 pixel gap, FixedWidth(width: 50, child: ...) to pin a
child at exactly 50 pixels, or FixedWidth(child: ...) with no width to fix a
child at its own preferred width. If the fixed widths alone exceed the
available space, they shrink proportionally to each other, so the row still
never overflows.
AnimatedBetween now reports proper intrinsic dimensions, so it can be used inside parents that measure children by intrinsics (IntrinsicWidth, Intrins
AnimatedBetween now reports proper intrinsic dimensions, so it can be used
inside parents that measure children by intrinsics (IntrinsicWidth,
IntrinsicHeight, RowSuper, etc.). At rest it reports its child's
intrinsics; mid-transition it reports the current animated box size, so
intrinsic-measuring parents animate along. Visual behavior is unchanged.ThousandsSeparatorTextInputFormatter now accepts an allowedIntegerDigits parameter that limits the integer part to the given number of digits, just li
ThousandsSeparatorTextInputFormatter now accepts an allowedIntegerDigits
parameter that limits the integer part to the given number of digits, just
like allowedDecimals limits the fractional part. Leading zeros don't count
toward the limit, since they are stripped anyway.New OtpCodeVerificationField widget for one-time-password / verification flows: a row of digit boxes that auto-submits when the last character is ente
New OtpCodeVerificationField widget for one-time-password / verification
flows: a row of digit boxes that auto-submits when the last character is
entered, with built-in handling for wrong-code, verification-failure, and
expiry states, plus an optional countdown timer. Accepted characters are
configurable via codeType, codeLetterSet, codeLetterCasing, and
customSet, and almost everything visual can be customized.
New Email class for email-address handling: isValid() validates an
address (with optional top-level-domain and international-character support),
sanitize() strips obviously invalid characters, and tryFix() attempts to
repair an invalid address into a valid one. The matching
EmailTextInputFormatter uses sanitize() to strip invalid characters as
the user types.
New CapitalizationTextInputFormatter capitalizes text as the user types,
with options for uppercase, lowercase, first-letter, or English title case.
New NumbersTextInputFormatter allows only numeric input — integer, or
decimal with locale-aware, dot, or comma separators.
New AllowedCharsTextInputFormatter allows only the characters that match a
given regular expression, filtering out everything else.
New NoSpacesTextInputFormatter prevents the user from typing any whitespace,
removing spaces, tabs, and newlines from the input.
New AlwaysAtTheEndTextInputFormatter forces the cursor to always stay at the
end of the text being typed.
New StringDotLengthLimiterTextInputFormatter limits text by Dart's
String.length (instead of grapheme clusters), useful when matching server,
database, or file-format limits.
Nothing published for this version
Nothing published for this version
Widget KeyboardDismiss is now deprecated.
Widget KeyboardDismiss is now deprecated.
To fix the deprecation warning, replace:
KeyboardDismiss(child: ...)
with:
Keyboard(
iOsCloseOnTap: true,
iOsCloseOnSwipe: true,
iOsRemoveFocusOnTap: true,
child: ...
)
The new Keyboard widget allows you to show different content depending on whether
the system keyboard is open or closed. If also controls the behavior of the system
keyboard on both iOS and Android, including auto-dismissing the keyboard when the user
taps outside it or swipes down from just above the keyboard edge.
Place the Keyboard widget near the top of the widget tree, where it has the same size
as the screen, for example, in MaterialApp.builder, above any Scaffold. For example:
MaterialApp(
builder: (BuildContext context, Widget? child) =>
Keyboard(
iOsCloseOnTap: true,
iOsCloseOnSwipe: true,
iOsRemoveFocusOnTap: true,
child: ...,
);
Here are the constructor parameters:
iOsCloseOnTap closes the keyboard when the user taps an empty
area of the screen, on the iOS.iOsCloseOnSwipe closes the keyboard when the user swipes down
from just above the keyboard edge, on the iOS.iOsRemoveFocusOnTap controls whether focus is also removed from any focused
element when the keyboard is dismissed by a tap, on the iOS.iOsRemoveFocusOnSwipe controls whether focus is also removed from any focused
element when the keyboard is dismissed by a swipe, on the iOS.androidCloseOnTap closes the keyboard when the user taps an empty
area of the screen, on the Android.androidCloseOnSwipe closes the keyboard when the user swipes down
from just above the keyboard edge, on the Android.androidRemoveFocusOnTap controls whether focus is also removed from any focused
element when the keyboard is dismissed by a tap, on the Android.androidRemoveFocusOnSwipe controls whether focus is also removed from any focused
element when the keyboard is dismissed by a swipe, on the Android.The default is false for all the above parameters.
On the iOS, it's common for the keyboard to auto-dismiss when the user taps outside it or swipes down from just above the keyboard edge. Usually, when the keyboard is dismissed by a tap, the focused element also loses focus, but when it's dismissed by a swipe, the focused element retains focus (and may re-open the keyboard if it's tapped).
On the Android, the default is that the keyboard only closes when the user taps the back button or executes the back gesture.
For these reasons, the recommended configuration is:
Keyboard(
iOsCloseOnTap: true,
iOsCloseOnSwipe: true,
iOsRemoveFocusOnTap: true,
child: ...
);
Keyboard.isOpen(context) can be used to check whether the keyboard is currently open
or not. Example usage: bool isKeyboardOpen = Keyboard.isOpen(context);.
Use Keyboard.open() and Keyboard.close() to programmatically open and close the
system keyboard.
The new KeyboardSwitch widget renders different content depending on whether
the system keyboard is open or closed. There are two ways to use it:
The default constructor takes optional open and closed widgets. The open
widget is shown when the keyboard is open, and the closed widget when it is
closed. Both are optional, and a missing slot renders nothing. Example usage:
KeyboardSwitch(
open: Text('Keyboard is open'),
closed: Text('Keyboard is closed'),
)
The KeyboardSwitch.builder constructor takes a builder callback that receives
the current isOpen state, so you can build any widget you want based on it.
Example usage:
KeyboardSwitch.builder(
(context, isOpen) => Icon(isOpen ? Icons.keyboard : Icons.keyboard_hide),
)
Note KeyboardSwitch only works if you add a Keyboard widget ancestor.
An error will be thrown if you try to use it without a Keyboard ancestor.
Nothing published for this version
Added AnimatedBetween widget, which animates smoothly between two children, cross-fading their content while resizing the enclosing box. The old and n
AnimatedBetween widget, which animates smoothly between two children,
cross-fading their content while resizing the enclosing box. The old and new
children can differ in both width and height, and their sizes don't need to be
known in advance. The convenience constructor AnimatedBetween.showHide animates
a single widget in and out.Nothing published for this version
Nothing published for this version
Added ThousandsSeparatorTextInputFormatter, a formatter for your text-field that formats numeric input with thousands separators as the user types, wh
Added ThousandsSeparatorTextInputFormatter, a formatter for your text-field that
formats
numeric input with thousands separators as the user types, while preserving the caret
position. It accepts integers and decimals.
Added KeepTallest widget, which tracks its child's height and never visually shrinks
below the tallest height observed so far. Useful for preventing layout jumps when
switching between children of different heights (e.g. tab content inside scrollables).
Optionally supports animated shrinking back to the child's natural height, with
configurable delay, duration, curve, and minimum shrink threshold.
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Fixed Button visual bug: When delay is true and the user taps quickly (before the delay timer fires), the visual press feedback now still shows briefl
Bumped environment:
Fixed Button visual bug: When delay is true and the user taps quickly (before the
delay timer fires), the visual press feedback now still shows briefly using
minVisualTapDuration, instead of being skipped entirely.
Breaking change: The signature of the builders of TimeBuilder have been changed. They all now use named parameters, and also get a new initialTime par…
TimeBuilder have been changed.
They all now use named parameters, and also get a new initialTime parameter that
was not present before. Migration should be straightforward, Refer to the README for
more information.Nothing published for this version
The ScrollShadow widget adds a shadow at the top and/or bottom, to scrollables like SingleChildScrollView or ListView etc., when the content doesn't f
ScrollShadow widget adds a shadow at the top and/or bottom, to scrollables like
SingleChildScrollView or ListView etc., when the content doesn't fit the
scrollable's viewport. As the shadow appears only if there is content outside the
viewable area, this gives the user an indication if there is more content to be seen
or not.The DetectScroll widget can detect if the content of a Scrollable is larger than the Scrollable itself, which means that the content can be scrolled,
The DetectScroll widget can detect if the content of a Scrollable is larger than the
Scrollable itself, which means that the content can be scrolled, and that a scrollbar
is likely visible. It can also tell you the probable width of that scrollbar.
This is useful for positioning widgets relative to the scrollbar, so that the scrollbar doesn't overlap them. This can be important when the scrollbar is permanently visible, usually on the Web and desktop.
Note that DetectScroll will only detect the scrolling of its closest scrollable
descendant (a scrollable is a SingleChildScrollView, ListView, GridView etc.).
Usually, you'd wrap the scrollable you care about directly with a DetectScroll.
For example:
DetectScroll (child: SingleChildScrollView (child: Column (... ... );
To get the current scroll state and the scrollbar width, descendants can call:
bool canScroll = DetectScroll.of (context).canScroll; double scrollbarWidth = DetectScroll.of (context).scrollbarWidth;
For example, suppose you want to add a help button to the top-right corner of a
scrollable, and account for the scrollbar width only if it's visible:
bool canScroll = DetectScroll.of (context).canScroll; double scrollbarWidth = DetectScroll.of (context).scrollbarWidth;
return Stack (children: [ child, Positioned (right: canScroll ? scrollbarWidth : 0, top: 0, child: HelpButton (), ), ], );
Another alternative is using the optional `onChange` callback of the `DetectScroll`:
DetectScroll (onChange: ({ required bool canScroll, required double scrollbarWidth, }) { // Do something. } child: ... ),
Nothing published for this version
The SideBySide widget now has a mainAxisSize property the determines whether it will occupy the full available width (MainAxisSize.max) or only as muc
SideBySide widget now has a mainAxisSize property the determines whether it
will occupy the full available width (MainAxisSize.max) or only as much as it
needs (MainAxisSize.min).Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
CircleButton now accepts an optional custom builder function to modify the button's child widget. This can be used to animate the button when the butt
CircleButton now accepts an optional custom builder function to modify the button's
child widget. This can be used to animate the button when the button is tapped,
or when the mouse is over it. For example:
CircleButton (icon: Icon (Icons.shopping_cart),
builder: ({
required bool isHover,
required bool isPressed,
required Widget child,
}) =>
AnimatedScale (scale: isPressed ? 0.85 : 1.0,
duration: const Duration (milliseconds: 50),
child: child,
),
);
Try running
the [example](https://github.com/marcglasberg/assorted_layout_widgets/blob/master/example/lib/main_button_and_circle_button.dart).
Deprecated usage: The startChild and endChild parameters are deprecated. Use the children parameter instead. The innerDistance parameter is also depre…
SideBySide widget now allows for any number of children, not just two. Example:
SideBySide (children: [ Text ("Hello!", textWidthBasis: TextWidthBasis.longestLine), Text ("How are you?", textWidthBasis: TextWidthBasis.longestLine), Text ("I'm good, thank you.", textWidthBasis: TextWidthBasis.longestLine), ], gaps: [8.0, 12.0], );
The `SideBySide` widget achieves layouts that are not possible with `Row` or `RowSuper`
widgets. Read the documentation for more information.
**Deprecated usage:** The `startChild` and `endChild` parameters are deprecated.
Use the `children` parameter instead. The `innerDistance` parameter is also deprecated.
Use the `gaps` parameter instead.
For example, this deprecated code:
return SideBySide (startChild: Text ("Hello!", textWidthBasis: TextWidthBasis.longestLine), endChild: Text ("How are you?", textWidthBasis: TextWidthBasis.longestLine), innerDistance: 8.0, );
Should be replaced with:
return SideBySide (children: [ Text ("Hello!", textWidthBasis: TextWidthBasis.longestLine), Text ("How are you?", textWidthBasis: TextWidthBasis.longestLine), ], gaps: [8.0], );
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
The Box widget can now have a decoration, as well as a decorationPosition. Previously, if a Container had a decoration you could not replace it with a
The Box widget can now have a decoration, as well as a decorationPosition.
Previously, if a Container had a decoration you could not replace it with a Box,
but now you can. Note the Box is a little more flexible than the Container when you
define a color and a BoxDecoration or a ShapeDecoration at the same time, as
the Box will only throw an error if the color is defined twice.
You can use Box.gap() to create a small gap between widgets:
Column (children: [ Text ('A'), const Box.gap (8), // 8.0 pixel gap Text ('B'), ]);
Nothing published for this version
Nothing published for this version
Fixed GestureDetector ordering issue for RowSuper and ColumnSuper when the invert param is true.
GestureDetector ordering issue for RowSuper and ColumnSuper when
the invert param is true.Removed KeyboardDismiss dependency on dart:io to make it compatible with platform web.
Removed KeyboardDismiss dependency on dart:io to make it compatible with platform
web.
Now CircleButton can specify hoverColor (default is no color),
and cursor (the default is SystemMouseCursors.click, but you can pass null to
set it as MouseCursor.defer).
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →