flutter_android_widgets

Multiple Widgets

Each top-level final or const variable of type AndroidWidget in your lib/ folder becomes its own home screen widget. There's no extra configuration — just declare them.


Defining multiple widgets

// lib/widgets.dart
import 'package:flutter_android_widgets/flutter_android_widgets.dart';

final weatherWidget = AndroidWidget(
  info: WidgetInfo(
    widgetClassName: 'WeatherWidgetProvider',
    widgetName: 'Weather',
    minWidth: 250,
    minHeight: 100,
    updateInterval: Duration(hours: 1),
  ),
  layout: WColumn(
    backgroundColor: '#1A237E',
    padding: 12,
    children: [
      WText('\${temperature}', textSize: 36, bold: true, textColor: '#FFFFFF'),
      WText('\${condition}', textSize: 14, textColor: '#B0BEC5'),
    ],
  ),
  dataKeys: ['temperature', 'condition'],
);

final todoWidget = AndroidWidget(
  info: WidgetInfo(
    widgetClassName: 'TodoWidgetProvider',
    widgetName: 'Todo List',
    minWidth: 250,
    minHeight: 200,
    updateInterval: Duration(minutes: 30),
  ),
  layout: WColumn(
    backgroundColor: '#263238',
    padding: 12,
    children: [
      WText('Tasks', textSize: 16, bold: true, textColor: '#FFFFFF'),
      WText('\${task1}', textSize: 14, textColor: '#CFD8DC'),
      WText('\${task2}', textSize: 14, textColor: '#CFD8DC'),
      WText('\${task3}', textSize: 14, textColor: '#CFD8DC'),
      WButton(label: 'Refresh', actionKey: 'refreshTodo'),
    ],
  ),
  dataKeys: ['task1', 'task2', 'task3'],
);

What gets generated

Running build_runner produces separate files for each widget:

WidgetXML layoutProvider XMLKotlin class
weatherWidgetwidget_weather_widget_provider.xmlappwidget_provider_weather_widget_provider.xmlWeatherWidgetProvider.kt
todoWidgetwidget_todo_widget_provider.xmlappwidget_provider_todo_widget_provider.xmlTodoWidgetProvider.kt

Both <receiver> entries are patched into AndroidManifest.xml together.


Sending data to multiple widgets

Data keys are global across all widgets. Use distinct key names to avoid collisions:

// Weather data
await HomeWidgetData.saveAll({
  'temperature': '72°F',
  'condition': 'Sunny',
});

// Todo data
await HomeWidgetData.saveAll({
  'task1': '✓ Buy groceries',
  'task2': '○ Call dentist',
  'task3': '○ Review PR',
});

Passing all widgets to WidgetUpdater

Pass the full list to initialize() so all widget styles sync on hot restart:

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  WidgetUpdater.initialize(widgets: [weatherWidget, todoWidget]);
  HomeWidgetData.autoUpdate = true;
  runApp(const MyApp());
}

Widgets across multiple files

You can spread widget definitions across multiple files. The builder scans all .dart files under lib/:

lib/
├── widgets/
│   ├── weather_widget.dart   ← final weatherWidget = AndroidWidget(...)
│   ├── todo_widget.dart      ← final todoWidget = AndroidWidget(...)
│   └── stats_widget.dart     ← final statsWidget = AndroidWidget(...)
└── main.dart

Action key uniqueness

Button actionKey values must be globally unique across all widgets. The generator creates a broadcast action constant per key:

actionKey: 'refresh'  →  ACTION_REFRESH = "com.example.myapp.ACTION_REFRESH"
actionKey: 'refreshTodo'  →  ACTION_REFRESHTODO = "com.example.myapp.ACTION_REFRESHTODO"

Using the same actionKey in two different widgets would cause both to respond to the same broadcast — leading to unexpected behavior.

On this page

No Headings