You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Native Home Screen Widgets for the Flet Framework (after thorough discussion with Antigravity)
#6783
Currently, Python mobile frameworks (Flet, BeeWare/Toga, Kivy) do not provide a native mechanism for creating Android Home Screen Widgets (AppWidget) or iOS Home Screen Widgets (WidgetKit).
This RFC proposes a Pure-Python Declarative Widget DSL and an Automated Build-Time Transpiler / Code Generator integrated into flet-cli. Developers define their home screen widget using familiar, declarative Python code, and the Flet build pipeline automatically synthesizes the native Android Kotlin/XML code (and iOS Swift/SwiftUI code) during flet build.
🔍 Technical Background & The Core Challenge
Why Frameworks Cannot Draw Widgets at Runtime
Flutter / Flet App Model: Runs inside an active Activity (Android) or UIWindow (iOS) where Skia/Impeller renders pixels to a canvas at 60/120fps.
OS Home Screen Widgets Model: Widgets run inside the OS Launcher Process (e.g., Samsung One UI Home, Google Pixel Launcher, iOS SpringBoard).
OS Constraint: For battery, memory, and security reasons, Android limits widgets strictly to RemoteViews (a small subset of native Views: TextView, ImageView, LinearLayout, ListView, etc.). The OS does not allow spinning up a live Flutter engine, Dart VM, or Python interpreter inside the Launcher.
The Solution: The Shared State Bridge
Because flet.SharedPreferences already persists key-value data directly to Android's FlutterSharedPreferences and iOS's UserDefaults, the widget can be written as native platform code that reads this shared state and updates upon OS alarms or broadcasts.
🔬 How Flutter Currently Implements Home Screen Widgets (State of the Art & Comparison)
In the standard Flutter ecosystem, developers rely on three main paradigms. Understanding these approaches provides valuable insights for Flet's architecture:
1. The home_widget Plugin (Shared Storage + Manual Native Boilerplate)
The most widely adopted package in Flutter is home_widget.
How It Works:
Dart writes key-value data using HomeWidget.saveWidgetData('key', 'value').
Dart triggers a reload via HomeWidget.updateWidget(name: 'MyWidgetProvider').
The developer must manually write the Android Kotlin AppWidgetProvider, layout XMLs, and iOS Swift WidgetKit code in android/ and ios/.
Pain Point in Flet: Because flet build dynamically recreates or overwrites build/flutter/, standard home_widget manual native coding is fragile and gets wiped out unless custom pre-build scripts intercept the process.
2. Headless Offscreen Rasterization (renderFlutterWidget to PNG)
An alternative technique provided by home_widget is offscreen widget rasterization:
How It Works:
The Flutter engine renders an arbitrary Flutter widget tree offscreen using RepaintBoundary and converts it to a PNG bitmap with toImage().
The PNG is saved to the shared app storage directory.
The native AppWidgetProvider simply loads this image into a single full-bleed ImageView via RemoteViews.setImageViewBitmap().
Pros: Allows using any arbitrary Flutter layout, gradients, custom canvas drawings, and charts directly.
Cons:
No Sub-Element Interactivity: The widget is a static flat picture; individual buttons, checkboxes, or scrollable lists inside the widget cannot be clicked independently.
Memory & Battery Overhead: Writing high-resolution PNGs to flash memory on every tick causes battery drain and layout delays.
Accessibility & System Theming: Cannot adapt to Android dynamic Material You system colors or user system font scaling.
3. Jetpack Glance (Android) & WidgetKit (iOS)
Modern native mobile development uses declarative DSLs:
Android Jetpack Glance: Google's Kotlin Compose-based library that compiles declarative Kotlin UI into RemoteViews.
iOS WidgetKit: Apple's pure SwiftUI framework for home screen and lock screen widgets.
🚀 Why Flet's Proposed Transpiler Is a Generation Ahead
By implementing a Build-Time Transpiler in flet-cli, Flet can take the best of all worlds:
No Manual Native Coding: Unlike home_widget, developers do not need to open Android Studio or Xcode or write Kotlin/XML.
True Native RemoteViews: Unlike PNG rasterization, widgets are crisp native Android Views with full support for interactive buttons, checkboxes, scrollable lists, and Material You dynamic styling.
Dual-Mode Capability:
Mode A (Declarative Transpilation - Default): Python UI tree compiles directly to lightweight, battery-efficient native XML/Kotlin.
Mode B (Render-to-Image - Optional): For complex graphs or charts, Flet can optionally rasterize a view to PNG and display it inside a WidgetImage.
📐 Proposed Architecture: Pure-Python Widget DSL
1. Declarative Widget Definition (src/widget.py or widget_config.py)
Developers declare their widget in pure Python without writing a single line of Kotlin or XML:
importfletasftfromflet.widgetimport (
HomeWidget,
WidgetText,
WidgetColumn,
WidgetRow,
WidgetButton,
WidgetBinding,
WidgetAction,
)
classWeeknumWidget(HomeWidget):
name="WeeknumWidget"label="Week Number Widget"description="Displays the current ISO week number and date range"size= (2, 1) # 2 columns x 1 row (target grid)update_interval_hours=24# Android updatePeriodMillismidnight_rollover=True# Automated AlarmManager trigger at 00:00background="glass_dark"# Built-in presets: "glass_dark", "glass_light", "solid"defbuild(self):
returnWidgetColumn(
alignment="center",
padding=12,
controls=[
WidgetText(
id="widget_week_text",
# Dynamic binding mapped to SharedPreferences or Kotlin date logicvalue=WidgetBinding.ISO_WEEK_LABEL(
english="Week {week}",
greek="Εβδομάδα {week}",
),
size=20,
bold=True,
color="#FFFFFF",
shadow=True,
),
WidgetText(
id="widget_date_text",
value=WidgetBinding.DATE_RANGE(
format_key="format", # Reads preference "flutter.format"week_start_key="week_start"# Reads preference "flutter.week_start"
),
size=13,
color="#D0FFFFFF",
shadow=True,
),
],
on_click=WidgetAction.LAUNCH_APP, # PendingIntent to MainActivity
)
🛡️ Compile-Time / Runtime Validation Engine
Because RemoteViews does not support arbitrary Flet UI components or live Python lambdas, the parser must strictly validate the widget tree during build time:
classWidgetValidationError(Exception):
"""Raised when an invalid widget configuration or control is detected."""passALLOWED_WIDGET_CONTROLS= {
"WidgetText", "WidgetColumn", "WidgetRow", "WidgetContainer",
"WidgetImage", "WidgetButton", "WidgetProgressBar", "WidgetListView"
}
defvalidate_widget_tree(node):
node_type=node.__class__.__name__ifnode_typenotinALLOWED_WIDGET_CONTROLS:
raiseWidgetValidationError(
f"Control '{node_type}' is not supported in Home Screen Widgets.\n"f"Allowed controls: {', '.join(sorted(ALLOWED_WIDGET_CONTROLS))}."
)
# Reject live Python callablesifhasattr(node, "on_click") andcallable(node.on_click):
raiseWidgetValidationError(
f"Cannot use live Python callback '{node.on_click.__name__}' on {node_type}.\n"f"Home screen widgets run in the background launcher process without Python.\n"f"Use declarative actions like `WidgetAction.LAUNCH_APP` or `WidgetAction.SEND_BROADCAST`."
)
⚙️ Build Pipeline & Code Generation (flet-cli)
During flet build apk or flet build ipa, flet-cli inspects pyproject.toml or imports src/widget.py to synthesize all native assets before Gradle / Xcode compilation.
generator.py: Orchestrates layout XML and Kotlin/Swift generation.
android_xml.py: Transpiles Python tree to Android XML LinearLayout / TextView / ImageView.
kotlin_templates.py: Jinja2/string templates for AppWidgetProvider.kt.
src/flet_cli/commands/build.py:
Hook into _generate_flutter_app(): If widget configuration is detected in pyproject.toml or src/widget.py, generate native files before calling _run_flutter_command().
src/flet_cli/commands/build_base.py:
Patch AndroidManifest.xml with <receiver> and metadata tags automatically.
### Summary
This PR introduces **Declarative Home Screen Widgets** to Flet, allowing Python developers to create native Android `AppWidget` (and iOS `WidgetKit`) home screen widgets entirely in Python.
### Motivation & Problem Solved
Currently, no Python mobile framework allows building home screen widgets without manually creating native Android Kotlin/XML or iOS Swift files in the build tree. Because `flet build` regenerates the `build/flutter` directory, maintaining custom native widgets requires cumbersome pre-build interception scripts.
This feature enables:
1.**100% Python Widget Definition:** Layout, typography, sizing, and data bindings are declared in Python via `flet.widget`.
2.**Automated Build-Time Transpilation:**`flet-cli` parses the Python widget definition, generates the corresponding Kotlin `AppWidgetProvider` and Android XML layouts/drawables, and injects them into the Flutter project prior to Gradle compilation.
3.**Seamless State Sharing:** The widget automatically reads preferences stored by `ft.SharedPreferences()` (`FlutterSharedPreferences` on Android, `UserDefaults` on iOS).
4.**Compile-Time Validation:** Raises `WidgetValidationError` with clear guidance if unsupported controls or live Python callbacks are placed in a widget.
### Test Plan-[x] Defined 2x1 glassmorphic widget in Python.
-[x] Verified Android XML layout and Kotlin provider generation.
-[x] Verified midnight `AlarmManager` updates and system date change broadcasts.
-[x] Verified `FlutterSharedPreferences` preference propagation (week start day, format, language).
-[x] Verified app launch via widget tap `PendingIntent`.
-[x] Tested on physical Android 16 / API 36 device.
🏆 Key Benefits
Zero Native Code for Developers: Python developers get native home screen widgets without touching Kotlin, Swift, or Android XML.
Cross-Platform Foundation: The same declarative layout can target both Android RemoteViews and iOS WidgetKit.
Ecosystem First: Positions Flet as the first and only Python mobile framework with first-class home screen widget support.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
🎯 Executive Summary
Currently, Python mobile frameworks (Flet, BeeWare/Toga, Kivy) do not provide a native mechanism for creating Android Home Screen Widgets (
AppWidget) or iOS Home Screen Widgets (WidgetKit).This RFC proposes a Pure-Python Declarative Widget DSL and an Automated Build-Time Transpiler / Code Generator integrated into
flet-cli. Developers define their home screen widget using familiar, declarative Python code, and the Flet build pipeline automatically synthesizes the native Android Kotlin/XML code (and iOS Swift/SwiftUI code) duringflet build.🔍 Technical Background & The Core Challenge
Why Frameworks Cannot Draw Widgets at Runtime
Activity(Android) orUIWindow(iOS) where Skia/Impeller renders pixels to a canvas at 60/120fps.RemoteViews(a small subset of native Views:TextView,ImageView,LinearLayout,ListView, etc.). The OS does not allow spinning up a live Flutter engine, Dart VM, or Python interpreter inside the Launcher.The Solution: The Shared State Bridge
Because
flet.SharedPreferencesalready persists key-value data directly to Android'sFlutterSharedPreferencesand iOS'sUserDefaults, the widget can be written as native platform code that reads this shared state and updates upon OS alarms or broadcasts.🔬 How Flutter Currently Implements Home Screen Widgets (State of the Art & Comparison)
In the standard Flutter ecosystem, developers rely on three main paradigms. Understanding these approaches provides valuable insights for Flet's architecture:
1. The
home_widgetPlugin (Shared Storage + Manual Native Boilerplate)The most widely adopted package in Flutter is
home_widget.HomeWidget.saveWidgetData('key', 'value').HomeWidget.updateWidget(name: 'MyWidgetProvider').AppWidgetProvider, layout XMLs, and iOS SwiftWidgetKitcode inandroid/andios/.flet builddynamically recreates or overwritesbuild/flutter/, standardhome_widgetmanual native coding is fragile and gets wiped out unless custom pre-build scripts intercept the process.2. Headless Offscreen Rasterization (
renderFlutterWidgetto PNG)An alternative technique provided by
home_widgetis offscreen widget rasterization:RepaintBoundaryand converts it to a PNG bitmap withtoImage().AppWidgetProvidersimply loads this image into a single full-bleedImageViewviaRemoteViews.setImageViewBitmap().3. Jetpack Glance (Android) & WidgetKit (iOS)
Modern native mobile development uses declarative DSLs:
RemoteViews.🚀 Why Flet's Proposed Transpiler Is a Generation Ahead
By implementing a Build-Time Transpiler in
flet-cli, Flet can take the best of all worlds:home_widget, developers do not need to open Android Studio or Xcode or write Kotlin/XML.WidgetImage.📐 Proposed Architecture: Pure-Python Widget DSL
1. Declarative Widget Definition (
src/widget.pyorwidget_config.py)Developers declare their widget in pure Python without writing a single line of Kotlin or XML:
🛡️ Compile-Time / Runtime Validation Engine
Because
RemoteViewsdoes not support arbitrary Flet UI components or live Python lambdas, the parser must strictly validate the widget tree during build time:⚙️ Build Pipeline & Code Generation (
flet-cli)During
flet build apkorflet build ipa,flet-cliinspectspyproject.tomlor importssrc/widget.pyto synthesize all native assets before Gradle / Xcode compilation.📁 Repository Structure & Required Changes
1. In
flet-dev/flet(Core Python Library)Add the new
flet.widgetsubmodule:sdk/python/packages/flet/src/flet/widget/(New Package)__init__.py: ExportsHomeWidget,WidgetText,WidgetColumn,WidgetRow, etc.base.py: Base classes andvalidate_widget_treevalidator.controls.py: Declarative definitions forWidgetText,WidgetImage,WidgetButton,WidgetListView.bindings.py: Standard bindings (ISO_WEEK_NUMBER,DATE_RANGE,PREFERENCE_KEY).actions.py:LAUNCH_APP,SEND_BROADCAST,DEEP_LINK.2. In
flet-dev/flet-cli(Build Tooling)Add widget code generation to the build command:
src/flet_cli/utils/widget/(New Package)generator.py: Orchestrates layout XML and Kotlin/Swift generation.android_xml.py: Transpiles Python tree to Android XMLLinearLayout/TextView/ImageView.kotlin_templates.py: Jinja2/string templates forAppWidgetProvider.kt.src/flet_cli/commands/build.py:_generate_flutter_app(): If widget configuration is detected inpyproject.tomlorsrc/widget.py, generate native files before calling_run_flutter_command().src/flet_cli/commands/build_base.py:AndroidManifest.xmlwith<receiver>and metadata tags automatically.3. Configuration in
pyproject.toml📝 Suggested GitHub Pull Request (PR) Message
🏆 Key Benefits
RemoteViewsand iOSWidgetKit.All reactions