Repository navigation
Performance improvements, Dismissible, widget capture, drawer and native image encoding (1.3.0)
This release brings performance improvements on both platforms,
Dismissible, widget capture, a native drawer on iPhone, and PNG and JPEG
encoding by the phone's own encoder. Simulator builds work again on
Xcode 26.
How to update. Run dn upgrade. This release needs a new version of
dn, so dn upgrade prints the install command for your system. Run that
command, then run dn upgrade again.
Code push. This release is a new framework build on a new engine.
After you update, the fixes you send reach only apps released with this
version. Make a new release of your app before you send fixes.
A change that can affect your code:
- If your app defines its own class named
ElevatedButton,TextButton,
OutlinedButtonorFilledButton, that name now also comes from
package:dartnative. Rename your class, or hide DartNative's:
import 'package:dartnative/dartnative.dart' hide TextButton;.
New
- A native drawer on iPhone. On the root screen,
Scaffold.draweris
now the drawer that UIKit apps use. The panel sits behind the app, and
opening it slides the whole screen aside, navigation bar and tab bar
included. The app bar stays the system bar, so its buttons morph into the
next screen's buttons when you push a screen, and back when you pop it,
also in an app with a drawer. Both styles remain:DrawerStyle.push, and
slideOverwith its shadow and rounded corners. Swipe to open, tap to
close,Scaffold.of(context).openDrawer()andonDrawerChangedwork as
before. You do not need to change your app. A screen pushed on top that
has its own drawer keeps that drawer. Dismissible. Flutter's widget for swiping a row away. Drag a row
and itsbackgroundshows in the space it leaves. If you release the row
past its threshold, or fling it, it slides off, unlessconfirmDismiss
keeps it. The list then closes the gap and callsonDismissed. All of
Flutter's fields work, in aListView, aFastListor anywhere else.- Capture a widget as an image. Wrap the widget in a
RepaintBoundary
with aGlobalKey, then call
(key.currentContext!.findRenderObject() as RenderRepaintBoundary).toImage(pixelRatio: 3),
as in Flutter. Importpackage:dartnative/canvas.dartasuiwhere
Flutter code importsdart:ui. - Native image encoding, PNG and JPEG.
image.toByteData(format: ui.ImageByteFormat.png)gives a PNG file, as in Flutter.
image.toJpeg(quality: 90)gives a JPEG file, at a quality from 0 to
100. Flutter has no JPEG encoder, so Flutter apps add a package for it.
We built it into DartNative, because encoding an image, like decoding
one, is a core feature that should not need a plugin. The phone's own
encoder makes both files, without holding up the screen. On an iPhone 16 Pro
and a Xiaomi 11 Lite, a JPEG took 2 to 10 ms, about four times faster
than Flutter with theimagepackage. A PNG took 14 to 27 ms, three to
four times faster than Flutter's own encoder. On iPhone the PNG is made
for speed rather than size, so use a JPEG when you need a small file. A
JPEG has no transparency: transparent areas come out white. context.sizeandfindRenderObject()work on any widget. In a
StatelessWidgetor aStatefulWidgetthey now answer as in Flutter.
Before, they returned null.FastList.cacheExtent. Keeps rows built up to a distance in points
beyond the screen, as in Flutter. UnlikekeepAliveCount, which counts
rows, it holds the same memory whatever your rows contain.- Reused rows in
FastList. SetrecycleItems: truetogether with
keepAliveCountorcacheExtent. Rows that leave the screen are then
reused for the rows that scroll in, as the platform's own lists do. - The buttons come with the main import.
ElevatedButton,
TextButton,OutlinedButtonandFilledButtonnow come with
package:dartnative/dartnative.dart, so that one import is enough for a
new app or a ported Flutter app.flutter_compat.dartstill works. It is
now the same library, marked as deprecated, so your editor suggests the
new import. IconButtonshows a press on Android. Pressing it draws the
platform's ripple, the circle that toolbar icons show under your finger.Interval. Flutter's curve that runs over part of an animation.- The soft scroll edge on iPhone. Under a bar with a title, iOS 27
draws a hard edge with a line, where iOS 26 faded the content softly. To
keep the soft fade, use
Scaffold(ios: ScaffoldIOSConfig(scrollEdgeEffectStyle: ScrollEdgeEffectStyle.soft)).
It applies to the screen's lists and scroll views where they run under a
bar: a clear or frosted app bar withextendBodyBehindAppBar, or the tab
bar withextendBody.hardasks for the hard edge. The default,
automatic, leaves the choice to the system. - An adaptive launcher icon for new Android apps. The logo fills the
phone's icon shape and follows themed icons. Before, it was a square
shrunk inside a white circle. To give an existing app the same icon, copy
packages/flutter_tools/templates/app/tool/generate_app_assets.dart.copy.tmpl
from the folder where DartNative is installed (~/zeroby default) over
your app'stool/generate_app_assets.dart. Then run it again:
dn pub run tool/generate_app_assets.dart --source=assets/your-logo.png.
The logo needs a transparent background.--bg=#RRGGBBsets the colour
behind it. - For plugin authors on Android:
mayDrawIntoSurface. If your plugin's
view draws onto the canvas it is given, returnfalsefrom your
provider'smayDrawIntoSurface, and lists that hold the view do less
work. The default,true, keeps a video or a Rive animation ready before
its row scrolls in. - Benchmarks. A new
benchmarksfolder in the repository compares
scrolling in DartNative with each platform's own code and with React
Native, on an iPhone and an Android phone.
Performance
- Faster launch on iPhone. Apps show their first screen sooner. The
launch logo no longer stays for a minimum time: it disappears as soon as
the first screen is ready. To keep a minimum time, set
DNSplashMinDurationinInfo.plist, in milliseconds. - Faster launch on Android. Apps show their first screen sooner. The
launch logo's minimum time (dartnative.splash.min_duration_msin the
manifest) now works on Android 12 and later. - Screens with a list appear sooner. A screen with a
FastListshows
its first rows sooner when it opens. - Smoother scrolling in
FastList. Lists scroll more smoothly on both
platforms. - 120 Hz while a list moves on iPhone. A moving list runs at the
display's full refresh rate, and slows down with the content as the
platform's own lists do. - Lists use less memory. Lists hold fewer rows in memory on both
platforms, including a list inside each row of another list. - Memory is freed while the app is idle. Unused memory is released
when the app is idle, never during a scroll. - Images appear sooner on iPhone. Network images are ready sooner, and
an image shown in several places at once is downloaded only once.
Plugins
To get a new plugin version, raise its constraint in pubspec.yaml or run
dn pub upgrade.
dartnative_lottie1.3.2. A chat full of stickers scrolls more
smoothly and uses less memory on both platforms. On Android, a sticker
that leaves the screen stops playing.dartnative_background,dartnative_camera,
dartnative_notificationsanddartnative_revenuecat1.0.2. Simulator
builds work with Xcode 26 again (see Fixed).dartnative_cameraalso
prints its log lines only when verbose logging is on.dartnative_audio,dartnative_connectivity,dartnative_firebase,
dartnative_permissionsanddartnative_system1.0.1,
dartnative_media_picker1.1.1,dartnative_onnxruntime1.6.5 and
dartnative_share1.0.3. They no longer print log lines at launch in
an Android release build.dartnative_splash1.0.2. On iPhone, apps use less memory once
they have started. To get this, rundn run-tool dartnative_splash:setup
in your app again.
Fixed
- Simulator builds work again on Xcode 26. Since 1.2.0, building for
the iOS simulator with Xcode 26 failed with "Slice is not page aligned".
If your app usesdartnative_background,dartnative_camera,
dartnative_lottie,dartnative_notificationsor
dartnative_revenuecat, also rundn pub upgradeafter you update,
because their new versions carry the same fix. - Android release builds no longer print DartNative's startup lines.
They now print only when verbose logging is on, as on iPhone. The plugin
versions listed above stop their own launch lines too, and
dn pub upgradebrings them. - Clean installs on Linux. The SDK download contained a hidden macOS
file next to every file. On Linux these became real files in the SDK,
andtarprinted a warning for each one. The new download has none, and
installing again removes the old ones. - Scrolling to an item lands on it. On Android,
scrollToIndexand
jumpToItemnow place the item wherealignmentasks, as on iPhone. On
both platforms, the list finishes the move even when rows it passes
change size. On Android, an animated scroll to an item
a few tall rows away goes straight to it, without passing it and coming
back. In a reversed list, such as a chat, the last part of the scroll
glides as in the platform's own reversed list. The scroll also starts
immediately: on a screen of heavy rows, the list used to wait up to half
a second after the tap. cacheWidthandcacheHeightwork on every image.Image.asset,
Image.fileandImage.memorynow decode at the size you give, as
Image.networkalready did, so a large photo shown small uses little
memory. On Android, the longest side now comes out at that size, as on
iPhone. Before, a wide photo came out about a third larger than asked.- An image fills a box that is fixed on both sides. An image in a
Containerwith a height, in aColumnthat stretches its children, or
in aListView, kept its own proportions and sat at the top of the box.
It now fills the box, andfitplaces the picture inside it, centred,
as in Flutter. When only the height is fixed, as in aRow, the image
keeps its proportions. Image.memoryon Android, in a box that takes its size from the
image. The image never appeared. It now shows at its own size, as
Image.fileandImage.assetdo.- An item builder gets the list's context. In
ListView.builder,
FastList, the grids and the sliver lists, the context passed to
itemBuilderhad nothing above it. SoTheme.of(context)returned the
default theme, andNavigator.of(context),showDialogandshowAlert
failed. It is now the list's own context, as in Flutter. ListTile.onTapandInkWellwork.ListTileacceptedonTapbut
never called it, andInkWelldid not show its child. Both now respond
to a press with the platform's feedback: the grey highlight of a table
row on iPhone, the ripple of a Material list item on Android.ListTile
addsonLongPressandenabled, andInkWellacceptssplashColor,
highlightColorandborderRadius.ListTilehas Material's height on Android. A one-line tile was
48 dp tall, while Flutter's and Material's are 56 dp. It is now at least
56 dp, or 72 dp with a subtitle, with its content centred, as in Flutter.
On iPhone it keeps the 70 pt row of a plain list.ElevatedButtonlooks like Material's elevated button on Android. It
used to be filled with the theme colour. It now has the light surface
colour, a label in the theme colour and a soft shadow, as in Flutter. On
iPhone it stays a filled button.Button(variant: ButtonVariant.elevated)
gives the same look.- Back returns to the previous screen on Android. On a screen pushed
without a route name, for example with
Navigator.push(context, PageRoute(builder: ...)), the system Back
gesture or button closed the app. It now returns to the screen below, as
it already did for named screens. - A sideways drag in a list keeps the touch on Android. A horizontal
drag on a row that drifted slightly up or down was taken over by the
list, which scrolled while the row snapped back. A drag that starts in
its own direction now keeps the touch, as on iPhone. A drag's end speed
is now the finger's speed as it lifts, not its average speed over the
whole drag. CustomPaintandHerowithflutter_compat.dart. That import gave
placeholder widgets that asked for Skia. It now gives the native widgets.- TalkBack reads the names of app bar buttons on Android.
Build: SDK 48fca8fe44f · engine 88fce5ef2577. Install or update: curl -fsSL https://cdn.dartnative.com/install.sh | sh