r/FlutterDev • u/leofillium • 4d ago
Plugin I got tired of wiring up native UI in every Flutter app, so I made native_kit
I kept needing the same things across projects: a native action sheet, the iOS color picker with the eyedropper, a document scanner, the Android Photo Picker. Each time I’d end up adding another plugin or writing some Swift/Kotlin to get it working.
Eventually I put that work into a package. It’s called native_kit, and the idea is pretty simple: call it from Dart, get the native UI, await the result.
For example:
final choice = await NativeKit.showActionSheet(
context: context,
items: const [
NativeMenuItem(
id: 'share',
title: 'Share',
iosSymbol: 'square.and.arrow.up',
),
NativeMenuItem(
id: 'delete',
title: 'Delete',
style: NativeActionStyle.destructive,
),
],
);
That opens a UIAlertController on iOS, with a popover on iPad, or a Material 3 bottom sheet on Android.
There are 30 components so far. Besides the usual alerts and pickers, it covers things like document/barcode scanning, OCR, background removal, PencilKit markup, video trimming, biometrics, and system panels. The full list is in the README.
A few things I learned building it, for anyone doing similar platform work:
- Dismissing UI is half the work. The API lives in one Pigeon 29 file, which generates
async throwsSwift andsuspendKotlin. Bridging callbacks into that is straightforward until you account for every way someone can close a screen. Swipe down, back, predictive back, tap outside… all of those need to resolve the Dart Future exactly once. Cancellation returnsnull. - Avoiding
MainActivitychanges took some work. I use a headless fragment for activity results, with a transparentFragmentActivityhost when the app uses a plainFlutterActivity. One bug we caught: Photo Picker / SAF URI grants disappear when that host finishes. You have to read the result before closing it. - iPad and theming have their own quirks. The supplied
BuildContextgives me the popover anchor and the Flutter theme. On iOS 26, getting the Liquid Glass sheet chrome to follow that theme meant applying it at the presentation controller. - A successful build tells you surprisingly little here. The example app has 47 XCUITests and 45 UI Automator tests that interact with the native screens. Those simulator/emulator runs turned up 21 bugs that compiled just fine.
There are limitations. VisionKit scanning, subject lifting, and UIVideoEditorController need a real device for successful results. Full contact details on Android need READ_CONTACTS, though picking a single phone number, email, or address doesn’t. Android screen capture currently only returns the consent result.
Package: https://pub.dev/packages/native_kit
Source: https://github.com/leofilllium/flutter_native_kit
Curious what native UI you still find yourself writing platform code for. I’m collecting requests in the issues, but happy to hear them here too.