porch 0.1.0
porch: ^0.1.0 copied to clipboard
In-app simulator for designing iOS WidgetKit and Android home screen widgets in Flutter. Hot-reload layouts against native sizes. Zero dependencies.
Porch #
In-app simulator for iOS WidgetKit and Android home-screen widgets. Lock a Flutter layout to a native family size, flip light / dark independently of the host app, and hot-reload padding, type, and constraints without a native build.
- No dependencies. Just Flutter.
- Native sizes. WidgetKit families and a Material 3 Android grid, or your
own
PorchFamilyfor a launcher-specific cell. - Forced preview theme. Light and dark on the widget, not on the rest of the app.
- Overflow you can see. A debug overlay when content wants more space than the frame allows.
- PNG for
home_widget. Capture the on-screen preview or render offscreen at a chosen pixel ratio.
Install #
dependencies:
porch: ^0.1.0
Quick start #
import 'package:porch/porch.dart';
PorchScaffold(
builder: (BuildContext context, PorchFamily family) {
return MyHomeWidget(compact: family == PorchFamily.systemSmall);
},
)
Or frame a single size with PorchBox:
PorchBox(
family: PorchFamily.systemMedium,
child: const MyHomeWidget(),
)
Inside the box, read the family the way SwiftUI reads @Environment(\.widgetFamily):
final PorchFamily family = PorchScope.of(context).family;
Families #
| Family | Size | Corners |
|---|---|---|
systemSmall |
158 × 158 pt | squircle r22 |
systemMedium |
338 × 158 pt | squircle r22 |
systemLarge |
338 × 354 pt | squircle r22 |
accessoryCircular |
72 × 72 pt | circle |
accessoryRectangular |
158 × 72 pt | rounded r12 |
cell2x2 |
160 × 160 dp | rounded r24 |
cell4x2 |
340 × 160 dp | rounded r24 |
cell4x4 |
340 × 340 dp | rounded r28 |
Logical pixels in Flutter equal points on iOS and dp on Android, so these sizes are applied as tight constraints.
Custom sizes are a constructor call:
const PorchFamily extraLarge = PorchFamily(
id: 'systemExtraLarge',
label: 'Extra Large',
size: Size(338, 354),
cornerRadius: 22,
);
PorchScaffold #
The playground: wallpaper, zoom, family chips, and a floating control bar.
PorchScaffold(
families: PorchFamily.ios, // or .android, .presets, or your own
wallpapers: PorchWallpaper.presets,
zoomPresets: const <double>[0.8, 1.0, 1.2],
lightTheme: ThemeData(brightness: Brightness.light, useMaterial3: true),
darkTheme: ThemeData(brightness: Brightness.dark, useMaterial3: true),
controls: const PorchControls(showWallpaper: false),
labels: const PorchLabels(light: 'Terang', dark: 'Gelap'),
extraControls: <Widget>[
// Dummy-data toggles, export buttons, …
],
previewBuilder: (BuildContext context, Widget child) {
return MyProviderScope(child: child);
},
builder: (BuildContext context, PorchFamily family) {
return const MyHomeWidget();
},
)
Drive it from outside with PorchController, or replace the toolbar with
controlBarBuilder. PorchWallpaper.custom takes a builder if the four
painted presets are not enough.
Snapshots #
On-screen, put a GlobalKey on PorchBox.snapshotKey (or pass it to
PorchScaffold) and call capture / capturePng.
Offscreen, render / renderPng build a throwaway pipeline — the usual path
into home_widget. Use PorchChrome.none so the OS can mask corners.
final Uint8List png = await PorchSnapshotHelper.renderPng(
const MyHomeWidget(),
family: PorchFamily.systemSmall,
pixelRatio: 3,
);
In widget tests, wrap those calls in tester.runAsync.
Version support #
| Dart | >=3.4.0 <4.0.0 |
| Flutter | >=3.22.0 |
| Package platforms | Android, iOS, web, macOS, Windows, Linux |
Pure Dart and Flutter widget tests run in CI on the oldest supported Flutter and on current stable.
Example #
A runnable demo lives in example/: a Daily Task Summary widget
that rearranges itself from systemSmall to systemMedium (and the rest), a
dummy-data switch, and an export sheet that shows both snapshot paths.
cd example
flutter run
License #
MIT