1. Einführung
Was sind Widgets?
Für Flutter-Entwickler bezieht sich die allgemeine Definition von Widget auf UI-Komponenten, die mit dem Flutter-Framework erstellt wurden. In diesem Codelab bezieht sich ein Widget auf eine Mini-Version einer App, die einen Einblick in die Informationen der App bietet, ohne die App zu öffnen. Auf Android befinden sich Widgets auf dem Startbildschirm. Unter iOS können sie dem Startbildschirm, dem Sperrbildschirm oder der Ansicht „Heute“ hinzugefügt werden.

Wie komplex kann ein Widget sein?
Die meisten Startbildschirm-Widgets sind einfach. Sie können einfachen Text, einfache Grafiken oder auf Android grundlegende Steuerelemente enthalten. Sowohl Android als auch iOS schränken ein, welche UI-Komponenten und Funktionen Sie verwenden können.

Benutzeroberfläche für Widgets erstellen
Aufgrund dieser Einschränkungen der Benutzeroberfläche können Sie die Benutzeroberfläche eines Startbildschirm-Widgets nicht direkt mit dem Flutter-Framework zeichnen. Stattdessen können Sie Ihrer Flutter-App Widgets hinzufügen, die mit Plattform-Frameworks wie Jetpack Compose oder SwiftUI erstellt wurden. In diesem Codelab werden Beispiele für das Teilen von Ressourcen zwischen Ihrer App und den Widgets behandelt, um das Umschreiben komplexer Benutzeroberflächen zu vermeiden.
Umfang
In diesem Codelab erstellen Sie mit dem Paket „home_widget“ Startbildschirm-Widgets für Android und iOS für eine einfache Flutter-App, mit der Nutzer Artikel lesen können. Ihre Widgets werden:
- Daten aus Ihrer Flutter-App anzeigen
- Text mit Schriftart-Assets anzeigen, die von der Flutter-App geteilt werden.
- Ein Bild eines gerenderten Flutter-Widgets anzeigen

Diese Flutter-App enthält zwei Bildschirme (oder Routen):
- Im ersten wird eine Liste von Nachrichtenartikeln mit Anzeigentiteln und Textzeilen angezeigt.
- Das zweite Bild zeigt den vollständigen Artikel mit einem Diagramm, das mit
CustomPainterstellt wurde.
.

Lerninhalte
- Hier erfährst du, wie du Startbildschirm-Widgets unter iOS und Android erstellst.
- So verwenden Sie das home_widget-Paket, um Daten zwischen Ihrem Startbildschirm-Widget und Ihrer Flutter-App freizugeben.
- So reduzieren Sie die Menge an Code, die Sie neu schreiben müssen.
- Startbildschirm-Widget über Ihre Flutter-App aktualisieren
2. Entwicklungsumgebung einrichten
Für beide Plattformen benötigen Sie das Flutter SDK und eine IDE. Sie können Ihre bevorzugte IDE für die Arbeit mit Flutter verwenden. Das kann Visual Studio Code mit den Dart Code- und Flutter-Erweiterungen oder Android Studio oder IntelliJ mit den installierten Flutter- und Dart-Plug-ins sein.
So erstellen Sie das iOS-Startbildschirm-Widget:
- Sie können dieses Codelab auf einem physischen iOS-Gerät oder im iOS-Simulator ausführen.
- Sie müssen ein macOS-System mit der Xcode-IDE konfigurieren. Dadurch wird der Compiler installiert, der zum Erstellen der iOS-Version Ihrer App erforderlich ist.
So erstellen Sie das Android-Startbildschirm-Widget:
- Sie können dieses Codelab auf einem physischen Android-Gerät oder im Android-Emulator ausführen.
- Sie müssen Ihr Entwicklungssystem mit Android Studio konfigurieren. Damit wird der Compiler installiert, der zum Erstellen der Android-Version Ihrer App erforderlich ist.
Startcode abrufen
Erste Version Ihres Projekts von GitHub herunterladen
Klonen Sie das GitHub-Repository über die Befehlszeile in ein Verzeichnis namens „flutter-codelabs“:
$ git clone https://github.com/flutter/codelabs.git flutter-codelabs
Nach dem Klonen des Repositorys finden Sie den Code für dieses Codelab im Verzeichnis „flutter-codelabs/homescreen_codelab“. Dieses Verzeichnis enthält den vollständigen Projektcode für jeden Schritt im Codelab.
Start-App öffnen
Öffnen Sie das Verzeichnis flutter-codelabs/homescreen_codelab/step_03 in Ihrer bevorzugten IDE.
Pakete installieren
Alle erforderlichen Pakete wurden der Datei „pubspec.yaml“ des Projekts hinzugefügt. Führen Sie den folgenden Befehl aus, um die Projektabhängigkeiten abzurufen:
$ flutter pub get
3. Einfaches Startbildschirm-Widget hinzufügen
Fügen Sie das Startbildschirm-Widget zuerst mit den nativen Plattformtools hinzu.
Einfaches iOS-Startbildschirm-Widget erstellen
Das Hinzufügen einer App-Erweiterung zu Ihrer Flutter-iOS-App ähnelt dem Hinzufügen einer App-Erweiterung zu einer SwiftUI- oder UIKit-App:
- Führen Sie
open ios/Runner.xcworkspacein einem Terminalfenster in Ihrem Flutter-Projektverzeichnis aus. Alternativ können Sie in VSCode mit der rechten Maustaste auf den Ordner ios klicken und In Xcode öffnen auswählen. Dadurch wird der Standard-Xcode-Arbeitsbereich in Ihrem Flutter-Projekt geöffnet. - Wählen Sie im Menü Datei → Neu → Ziel aus. Dadurch wird dem Projekt ein neues Ziel hinzugefügt.
- Eine Liste mit Vorlagen wird angezeigt. Wählen Sie Widget-Erweiterung aus.
- Geben Sie für dieses Widget „NewsWidgets“ in das Feld Produktname ein. Entfernen Sie die Häkchen aus den Kästchen Live-Aktivität einbeziehen und Konfigurationsabsicht einbeziehen.
Beispielcode ansehen
Wenn Sie ein neues Ziel hinzufügen, generiert Xcode Beispielcode basierend auf der ausgewählten Vorlage. Weitere Informationen zum generierten Code und zu WidgetKit finden Sie in der Dokumentation zu App-Erweiterungen von Apple .
Beispiel-Widget debuggen und testen
- Aktualisieren Sie zuerst die Konfiguration Ihrer Flutter-App. Das ist erforderlich, wenn Sie Ihrer Flutter-App neue Pakete hinzufügen und ein Ziel im Projekt über Xcode ausführen möchten. Führen Sie den folgenden Befehl im Verzeichnis Ihrer Flutter-App aus, um die Konfiguration Ihrer App zu aktualisieren:
$ flutter build ios --config-only
- Klicken Sie auf Runner, um eine Liste der Ziele aufzurufen. Wählen Sie das gerade erstellte Widget-Ziel „NewsWidgets“ aus und klicken Sie auf Ausführen. Führen Sie das Widget-Ziel in Xcode aus, wenn Sie den iOS-Widget-Code ändern.

- Auf dem Simulator oder Gerätebildschirm sollte ein einfaches Startbildschirm-Widget angezeigt werden. Wenn Sie sie nicht sehen, können Sie sie dem Bildschirm hinzufügen. Klicken Sie auf dem Startbildschirm und halten Sie die Maustaste gedrückt. Klicken Sie dann links oben auf das +.

- Suchen Sie nach dem Namen der App. In diesem Codelab suchen Sie nach „Homescreen Widgets“.

- Nachdem Sie das Startbildschirm-Widget hinzugefügt haben, sollte dort einfacher Text mit der Uhrzeit angezeigt werden.
Einfaches Android-Widget erstellen
- Wenn Sie in Android ein Startbildschirm-Widget hinzufügen möchten, öffnen Sie die Build-Datei des Projekts in Android Studio. Sie finden diese Datei unter „android/build.gradle“. Alternativ können Sie in VSCode mit der rechten Maustaste auf den Ordner android klicken und Open in Android Studio (In Android Studio öffnen) auswählen.
- Suchen Sie nach dem Erstellen des Projekts oben links nach dem App-Verzeichnis. Fügen Sie das neue Startbildschirm-Widget in dieses Verzeichnis ein. Klicken Sie mit der rechten Maustaste auf das Verzeichnis und wählen Sie Neu > Widget > App-Widget aus.

- In Android Studio wird ein neues Formular angezeigt. Fügen Sie grundlegende Informationen zu Ihrem Startbildschirm-Widget hinzu, z. B. den Klassennamen, die Platzierung, die Größe und die Quellsprache.
Legen Sie für dieses Codelab die folgenden Werte fest:
- Klassenname in „NewsWidget“
- Mindestbreite (Zellen) auf 3 festlegen
- Das Drop-down-Menü Mindesthöhe (Zellen) auf „3“ setzen
Beispielcode ansehen
Wenn Sie das Formular senden, werden in Android Studio mehrere Dateien erstellt und aktualisiert. Die für dieses Codelab relevanten Änderungen sind in der folgenden Tabelle aufgeführt.
Aktion | Zieldatei | Ändern |
Aktualisieren |
| Fügt einen neuen Receiver hinzu, der das News-Widget registriert. |
Erstellen |
| Definiert die Benutzeroberfläche des Startbildschirm-Widgets. |
Erstellen |
| Definiert die Konfiguration Ihres Startbildschirm-Widgets. In dieser Datei können Sie die Abmessungen oder den Namen Ihres Widgets anpassen. |
Erstellen |
| Enthält Ihren Kotlin-Code, um dem Startbildschirm-Widget Funktionen hinzuzufügen. |
Weitere Informationen zu diesen Dateien finden Sie in diesem Codelab.
Beispiel-Widget debuggen und testen
Führen Sie nun Ihre Anwendung aus und sehen Sie sich das Startbildschirm-Widget an. Nachdem Sie die App erstellt haben, rufen Sie auf Ihrem Android-Gerät den Bildschirm zur Auswahl der Anwendung auf und halten Sie das Symbol für dieses Flutter-Projekt gedrückt. Wählen Sie im Pop-up-Menü Widgets aus.

Auf dem Android-Gerät oder -Emulator wird das Standard-Startbildschirm-Widget für Android angezeigt.
4. Daten aus Ihrer Flutter-App an Ihr Startbildschirm-Widget senden
Sie können das von Ihnen erstellte einfache Startbildschirm-Widget anpassen. Das Startbildschirm-Widget wurde aktualisiert und zeigt jetzt eine Überschrift und eine Zusammenfassung für einen Nachrichtenartikel an. Der folgende Screenshot zeigt ein Beispiel für das Startbildschirm-Widget mit einer Überschrift und einer Zusammenfassung.

Wenn Sie Daten zwischen Ihrer App und dem Startbildschirm-Widget übergeben möchten, müssen Sie Dart- und nativen Code schreiben. In diesem Abschnitt wird dieser Prozess in drei Teile unterteilt:
- Dart-Code in Ihrer Flutter-App schreiben, der sowohl von Android als auch von iOS verwendet werden kann
- Native iOS-Funktionen hinzufügen
- Native Android-Funktionen hinzufügen
iOS-App-Gruppen verwenden
Wenn Sie Daten zwischen einer iOS-Haupt-App und einer Widget-Erweiterung teilen möchten, müssen beide Ziele zur selben App-Gruppe gehören. Weitere Informationen zu App-Gruppen finden Sie in der Dokumentation von Apple zu App-Gruppen.
Bundle-ID aktualisieren:
Rufen Sie in Xcode die Einstellungen Ihres Ziels auf. Prüfen Sie auf dem Tab Signing & Capabilities (Signierung & Funktionen), ob Ihr Team und Ihre Bundle-ID festgelegt sind.
Fügen Sie die App-Gruppe in Xcode sowohl dem Runner- als auch dem NewsWidgetExtension-Ziel hinzu:
Wählen Sie + Funktion -> App-Gruppen aus und fügen Sie eine neue App-Gruppe hinzu. Wiederholen Sie den Vorgang für das Runner-Ziel (übergeordnete App) und das Widget-Ziel.

Dart-Code hinzufügen
Sowohl iOS- als auch Android-Apps können Daten auf verschiedene Arten mit einer Flutter-App teilen.Für die Kommunikation mit diesen Apps können Sie den lokalen key/value-Speicher des Geräts verwenden. Unter iOS wird dieser Speicher als UserDefaults und unter Android als SharedPreferences bezeichnet. Das home_widget-Paket umschließt diese APIs, um das Speichern von Daten auf beiden Plattformen zu vereinfachen und es den Startbildschirm-Widgets zu ermöglichen, aktualisierte Daten abzurufen.

Die Daten für Anzeigentitel und Beschreibung stammen aus der Datei news_data.dart. Diese Datei enthält Beispieldaten und eine NewsArticle-Datenklasse.
lib/news_data.dart
class NewsArticle {
final String title;
final String description;
final String? articleText;
NewsArticle({
required this.title,
required this.description,
this.articleText = loremIpsum,
});
}
Werte für Anzeigentitel und Textzeile aktualisieren
Wenn Sie die Funktion zum Aktualisieren des Startbildschirm-Widgets über Ihre Flutter-App hinzufügen möchten, rufen Sie die Datei lib/home_screen.dart auf. Ersetzen Sie den Inhalt der Datei durch den folgenden Code. Ersetzen Sie dann <YOUR APP GROUP> durch die ID Ihrer App-Gruppe.
lib/home_screen.dart
import 'package:flutter/material.dart';
import 'package:home_widget/home_widget.dart'; // Add this import
import 'article_screen.dart';
import 'news_data.dart';
// TODO: Replace with your App Group ID
const String appGroupId = '<YOUR APP GROUP>'; // Add from here
const String iOSWidgetName = 'NewsWidgets';
const String androidWidgetName = 'NewsWidget'; // To here.
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key});
@override
State<MyHomePage> createState() => _MyHomePageState();
}
void updateHeadline(NewsArticle newHeadline) { // Add from here
// Save the headline data to the widget
HomeWidget.saveWidgetData<String>('headline_title', newHeadline.title);
HomeWidget.saveWidgetData<String>(
'headline_description', newHeadline.description);
HomeWidget.updateWidget(
iOSName: iOSWidgetName,
androidName: androidWidgetName,
);
} // To here.
class _MyHomePageState extends State<MyHomePage> {
@override // Add from here
void initState() {
super.initState();
HomeWidget.setAppGroupId(appGroupId);
// Mock read in some data and update the headline
final newHeadline = getNewsStories()[0];
updateHeadline(newHeadline);
} // To here.
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Top Stories'),
centerTitle: false,
titleTextStyle: const TextStyle(
fontSize: 30,
fontWeight: FontWeight.bold,
color: Colors.black)),
body: ListView.separated(
separatorBuilder: (context, idx) {
return const Divider();
},
itemCount: getNewsStories().length,
itemBuilder: (context, idx) {
final article = getNewsStories()[idx];
return ListTile(
key: Key('$idx ${article.hashCode}'),
title: Text(article.title!),
subtitle: Text(article.description!),
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) {
return ArticleScreen(article: article);
},
),
);
},
);
},
));
}
}
Mit der Funktion updateHeadline werden die Schlüssel/Wert-Paare im lokalen Speicher Ihres Geräts gespeichert. Der Schlüssel headline_title enthält den Wert von newHeadline.title. Der Schlüssel headline_description enthält den Wert von newHeadline.description. Die Funktion benachrichtigt auch die native Plattform, dass neue Daten für die Startbildschirm-Widgets abgerufen und gerendert werden können.
floatingActionButton ändern
Rufen Sie die Funktion updateHeadline auf, wenn die floatingActionButton gedrückt wird:
lib/article_screen.dart
// New: import the updateHeadline function
import 'home_screen.dart';
...
floatingActionButton: FloatingActionButton.extended(
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
content: Text('Updating home screen widget...'),
));
// New: call updateHeadline
updateHeadline(widget.article);
},
label: const Text('Update Homescreen'),
),
...
Wenn ein Nutzer auf einer Artikelseite auf die Schaltfläche Anzeigentitel aktualisieren klickt, werden die Widget-Details auf dem Startbildschirm aktualisiert.
iOS-Code aktualisieren, um die Artikeldaten anzuzeigen
Wenn Sie das Startbildschirm-Widget für iOS aktualisieren möchten, verwenden Sie Xcode.
Öffnen Sie die Datei NewsWidgets.swift in Xcode:
Konfigurieren Sie die TimelineEntry.
Ersetzen Sie die SimpleEntry-Struktur durch den folgenden Code:
ios/NewsWidgets/NewsWidgets.swift
// The date and any data you want to pass into your app must conform to TimelineEntry
struct NewsArticleEntry: TimelineEntry {
let date: Date
let title: String
let description:String
}
Diese NewsArticleEntry-Struktur definiert die eingehenden Daten, die bei einer Aktualisierung an das Startbildschirm-Widget übergeben werden sollen. Für den Typ TimelineEntry ist ein Datumsparameter erforderlich.Weitere Informationen zum TimelineEntry-Protokoll finden Sie in der Dokumentation zu TimelineEntry von Apple.
Bearbeiten Sie das View, in dem der Inhalt angezeigt wird.
Ändern Sie das Startbildschirm-Widget so, dass anstelle des Datums die Überschrift und die Beschreibung des Nachrichtenartikels angezeigt werden. Um Text in SwiftUI anzuzeigen, verwenden Sie die Text-Ansicht. Wenn Sie Ansichten in SwiftUI übereinander stapeln möchten, verwenden Sie die VStack-Ansicht.
Ersetzen Sie die generierte NewsWidgetEntryView-Ansicht durch den folgenden Code:
ios/NewsWidgets/NewsWidgets.swift
//View that holds the contents of the widget
struct NewsWidgetsEntryView : View {
var entry: Provider.Entry
var body: some View {
VStack {
Text(entry.title)
Text(entry.description)
}
}
}
Anbieter bearbeiten, um dem Startbildschirm-Widget mitzuteilen, wann und wie es aktualisiert werden soll
Ersetzen Sie den vorhandenen Provider durch den folgenden Code. Ersetzen Sie dann <YOUR APP GROUP> durch die Kennung Ihrer App-Gruppe:
ios/NewsWidgets/NewsWidgets.swift
struct Provider: TimelineProvider {
// Placeholder is used as a placeholder when the widget is first displayed
func placeholder(in context: Context) -> NewsArticleEntry {
// Add some placeholder title and description, and get the current date
NewsArticleEntry(date: Date(), title: "Placeholder Title", description: "Placeholder description")
}
// Snapshot entry represents the current time and state
func getSnapshot(in context: Context, completion: @escaping (NewsArticleEntry) -> ()) {
let entry: NewsArticleEntry
if context.isPreview{
entry = placeholder(in: context)
}
else{
// Get the data from the user defaults to display
let userDefaults = UserDefaults(suiteName: <YOUR APP GROUP>)
let title = userDefaults?.string(forKey: "headline_title") ?? "No Title Set"
let description = userDefaults?.string(forKey: "headline_description") ?? "No Description Set"
entry = NewsArticleEntry(date: Date(), title: title, description: description)
}
completion(entry)
}
// getTimeline is called for the current and optionally future times to update the widget
func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
// This just uses the snapshot function you defined earlier
getSnapshot(in: context) { (entry) in
// atEnd policy tells widgetkit to request a new entry after the date has passed
let timeline = Timeline(entries: [entry], policy: .atEnd)
completion(timeline)
}
}
}
Die Provider im vorherigen Code entspricht einer TimelineProvider. Provider hat drei verschiedene Methoden:
- Mit der Methode
placeholderwird ein Platzhalter-Eintrag generiert, wenn der Nutzer das Startbildschirm-Widget zum ersten Mal in der Vorschau ansieht.

- Die Methode
getSnapshotliest die Daten aus den Standardeinstellungen des Nutzers und generiert den Eintrag für die aktuelle Uhrzeit. - Die Methode
getTimelinegibt Zeitachseneinträge zurück. Das ist hilfreich, wenn Sie Ihre Inhalte zu bestimmten Zeiten aktualisieren. In diesem Codelab wird die Funktion „getSnapshot“ verwendet, um den aktuellen Status abzurufen. Die Methode.atEndweist das Startbildschirm-Widget an, die Daten nach Ablauf der aktuellen Zeit zu aktualisieren.
Kommentieren Sie NewsWidgets_Previews aus.
Die Verwendung von Vorschauen wird in diesem Codelab nicht behandelt. Weitere Informationen zur Vorschau von SwiftUI-Widgets auf dem Startbildschirm finden Sie in der Dokumentation von Apple zum Debuggen von Widgets.
Speichern Sie alle Dateien und führen Sie das App- und Widget-Ziel noch einmal aus.
Führen Sie die Ziele noch einmal aus, um zu prüfen, ob die App und das Startbildschirm-Widget funktionieren.
- Wählen Sie das App-Schema in Xcode aus, um das App-Ziel auszuführen.
- Wählen Sie das Erweiterungsschema in Xcode aus, um das Erweiterungsziel auszuführen.
- Rufen Sie in der App eine Artikelseite auf.
- Klicken Sie auf die Schaltfläche, um die Überschrift zu aktualisieren. Auch das Startbildschirm-Widget sollte den Titel aktualisieren.
Android-Code aktualisieren
XML für das Startbildschirm-Widget hinzufügen:
Aktualisieren Sie in Android Studio die im vorherigen Schritt generierten Dateien.Öffnen Sie die Datei res/layout/news_widget.xml. Damit werden die Struktur und das Layout Ihres Startbildschirm-Widgets definiert. Wählen Sie rechts oben Code aus und ersetzen Sie den Inhalt der Datei durch den folgenden Code:
android/app/res/layout/news_widget.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/widget_container"
style="@style/Widget.Android.AppWidget.Container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@android:color/white"
android:theme="@style/Theme.Android.AppWidgetContainer">
<TextView
android:id="@+id/headline_title"
style="@style/Widget.Android.AppWidget.InnerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:background="@android:color/white"
android:text="Title"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/headline_description"
style="@style/Widget.Android.AppWidget.InnerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/headline_title"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="4dp"
android:background="@android:color/white"
android:text="Title"
android:textSize="16sp" />
</RelativeLayout>
In diesem XML werden zwei Textansichten definiert: eine für den Anzeigentitel des Artikels und die andere für die Beschreibung des Artikels. In diesen Textansichten wird auch das Styling definiert. Sie werden in diesem Codelab immer wieder auf diese Datei zurückkommen.
Funktionen des News-Widgets aktualisieren
Öffnen Sie die Kotlin-Quellcodedatei NewsWidget.kt. Diese Datei enthält eine generierte Klasse namens NewsWidget, die die Klasse AppWidgetProvider erweitert.
Die Klasse NewsWidget enthält drei Methoden aus ihrer Superklasse. Sie ändern die onUpdate-Methode. Android ruft diese Methode für Widgets in festen Intervallen auf.
Ersetzen Sie den Inhalt der Datei NewsWidget.kt durch den folgenden Code:
android/app/java/com.mydomain.homescreen_widgets/NewsWidget.kt
// Import will depend on App ID.
package com.mydomain.homescreen_widgets
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.widget.RemoteViews
// New import.
import es.antonborri.home_widget.HomeWidgetPlugin
/**
* Implementation of App Widget functionality.
*/
class NewsWidget : AppWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray,
) {
for (appWidgetId in appWidgetIds) {
// Get reference to SharedPreferences
val widgetData = HomeWidgetPlugin.getData(context)
val views = RemoteViews(context.packageName, R.layout.news_widget).apply {
val title = widgetData.getString("headline_title", null)
setTextViewText(R.id.headline_title, title ?: "No title set")
val description = widgetData.getString("headline_description", null)
setTextViewText(R.id.headline_description, description ?: "No description set")
}
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
}
Wenn onUpdate aufgerufen wird, ruft Android mit der Methode the widgetData.getString() die neuesten Werte aus dem lokalen Speicher ab und ruft dann setTextViewText auf, um den im Startbildschirm-Widget angezeigten Text zu ändern.
Updates testen
Testen Sie die App, um sicherzustellen, dass die Startbildschirm-Widgets mit neuen Daten aktualisiert werden. Verwenden Sie auf den Artikelseiten die Schaltfläche Startseite aktualisieren FloatingActionButton, um die Daten zu aktualisieren. Das Startbildschirm-Widget sollte mit dem Artikel aktualisiert werden.

5. Benutzerdefinierte Schriftarten aus Flutter-Apps in iOS-Startbildschirm-Widgets verwenden
Bisher haben Sie das Startbildschirm-Widget so konfiguriert, dass Daten gelesen werden, die von der Flutter-App bereitgestellt werden. Die Flutter-App enthält eine benutzerdefinierte Schriftart, die Sie möglicherweise im Startbildschirm-Widget verwenden möchten. Sie können die benutzerdefinierte Schriftart im iOS-Widget für den Startbildschirm verwenden. Die Verwendung benutzerdefinierter Schriftarten in Startbildschirm-Widgets ist unter Android nicht möglich.
iOS-Code aktualisieren
Flutter speichert seine Assets im mainBundle von iOS-Anwendungen. Sie können über den Code Ihres Startbildschirm-Widgets auf Assets in diesem Bundle zugreifen.
Nehmen Sie in der NewsWidgetsEntryView-Struct in Ihrer NewsWidgets.swift-Datei die folgenden Änderungen vor:
Hilfsfunktion erstellen, um den Pfad zum Flutter-Asset-Verzeichnis abzurufen:
ios/NewsWidgets/NewsWidgets.swift
struct NewsWidgetsEntryView : View {
...
// New: Add the helper function.
var bundle: URL {
let bundle = Bundle.main
if bundle.bundleURL.pathExtension == "appex" {
// Peel off two directory levels - MY_APP.app/PlugIns/MY_APP_EXTENSION.appex
var url = bundle.bundleURL.deletingLastPathComponent().deletingLastPathComponent()
url.append(component: "Frameworks/App.framework/flutter_assets")
return url
}
return bundle.bundleURL
}
...
}
Registrieren Sie die Schriftart mit der URL zu Ihrer benutzerdefinierten Schriftartdatei.
ios/NewsWidgets/NewsWidgets.swift
struct NewsWidgetsEntryView : View {
...
// New: Register the font.
init(entry: Provider.Entry){
self.entry = entry
CTFontManagerRegisterFontsForURL(bundle.appending(path: "/fonts/Chewy-Regular.ttf") as CFURL, CTFontManagerScope.process, nil)
}
...
}
Aktualisieren Sie die Textansicht des Anzeigentitels, damit Ihre benutzerdefinierte Schriftart verwendet wird.
ios/NewsWidgets/NewsWidgets.swift
struct NewsWidgetsEntryView : View {
...
var body: some View {
VStack {
// Update the following line.
Text(entry.title).font(Font.custom("Chewy", size: 13))
Text(entry.description)
}
}
...
}
Wenn Sie das Startbildschirm-Widget ausführen, wird jetzt die benutzerdefinierte Schriftart für die Überschrift verwendet, wie im folgenden Bild dargestellt:

6. Flutter-Widgets als Bild rendern
In diesem Abschnitt wird ein Diagramm aus Ihrer Flutter-App als Startbildschirm-Widget angezeigt.
Dieses Widget bietet eine größere Herausforderung als der Text, den Sie auf dem Startbildschirm angezeigt haben. Es ist viel einfacher, das Flutter-Diagramm als Bild anzuzeigen, als es mit nativen UI-Komponenten neu zu erstellen.
Programmieren Sie Ihr Startbildschirm-Widget so, dass Ihr Flutter-Diagramm als PNG-Datei gerendert wird. Dieses Bild kann im Startbildschirm-Widget angezeigt werden.
Dart-Code schreiben
Fügen Sie auf der Dart-Seite die Methode renderFlutterWidget aus dem Paket „home_widget“ hinzu. Diese Methode verwendet ein Widget, einen Dateinamen und einen Schlüssel. Es wird ein Bild des Flutter-Widgets zurückgegeben und in einem freigegebenen Container gespeichert. Geben Sie den Bildnamen in Ihrem Code an und sorgen Sie dafür, dass das Startbildschirm-Widget auf den Container zugreifen kann. Mit key wird der vollständige Dateipfad als String im lokalen Speicher des Geräts gespeichert. So kann das Startbildschirm-Widget die Datei finden, wenn sich der Name im Dart-Code ändert.
In diesem Codelab stellt die Klasse LineChart in der Datei lib/article_screen.dart das Diagramm dar. Die Build-Methode gibt einen CustomPainter zurück, der dieses Diagramm auf dem Bildschirm zeichnet.
Öffnen Sie die Datei lib/article_screen.dart, um diese Funktion zu implementieren. Importieren Sie das Paket „home_widget“. Ersetzen Sie als Nächstes den Code in der _ArticleScreenState-Klasse durch den folgenden Code:
lib/article_screen.dart
import 'package:flutter/material.dart';
// New: import the home_widget package.
import 'package:home_widget/home_widget.dart';
import 'home_screen.dart';
import 'news_data.dart';
...
class _ArticleScreenState extends State<ArticleScreen> {
// New: add this GlobalKey
final _globalKey = GlobalKey();
String? imagePath;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.article.title!),
),
// New: add this FloatingActionButton
floatingActionButton: FloatingActionButton.extended(
onPressed: () async {
if (_globalKey.currentContext != null) {
var path = await HomeWidget.renderFlutterWidget(
const LineChart(),
fileName: 'screenshot',
key: 'filename',
logicalSize: _globalKey.currentContext!.size,
pixelRatio:
MediaQuery.of(_globalKey.currentContext!).devicePixelRatio,
);
setState(() {
imagePath = path as String?;
});
}
updateHeadline(widget.article);
},
label: const Text('Update Homescreen'),
),
body: ListView(
padding: const EdgeInsets.all(16.0),
children: [
Text(
widget.article.description!,
style: Theme.of(context).textTheme.titleMedium,
),
const SizedBox(height: 20.0),
Text(widget.article.articleText!),
const SizedBox(height: 20.0),
Center(
// New: Add this key
key: _globalKey,
child: const LineChart(),
),
const SizedBox(height: 20.0),
Text(widget.article.articleText!),
],
),
);
}
}
In diesem Beispiel werden drei Änderungen an der Klasse _ArticleScreenState vorgenommen.
Erstellt einen GlobalKey
Mit GlobalKey wird der Kontext des jeweiligen Widgets abgerufen, der benötigt wird, um die Größe des Widgets zu ermitteln .
lib/article_screen.dart
class _ArticleScreenState extends State<ArticleScreen> {
// New: add this GlobalKey
final _globalKey = GlobalKey();
...
}
Fügt imagePath hinzu
Im Attribut imagePath wird der Speicherort des Bildes gespeichert, an dem das Flutter-Widget gerendert wird.
lib/article_screen.dart
class _ArticleScreenState extends State<ArticleScreen> {
...
// New: add this imagePath
String? imagePath;
...
}
Fügt dem Widget den Schlüssel hinzu, der gerendert werden soll
_globalKey enthält das Flutter-Widget, das im Bild gerendert wird. In diesem Fall ist das Flutter-Widget das Center-Widget, das das LineChart enthält.
lib/article_screen.dart
class _ArticleScreenState extends State<ArticleScreen> {
...
Center(
// New: Add this key
key: _globalKey,
child: const LineChart(),
),
...
}
- Speichert das Widget als Bild
Die Methode renderFlutterWidget wird aufgerufen, wenn der Nutzer auf floatingActionButton klickt. Die resultierende PNG-Datei wird mit der Methode als „screenshot“ im freigegebenen Containerverzeichnis gespeichert. Die Methode speichert auch den vollständigen Pfad zum Bild als Dateinamen-Schlüssel im Gerätespeicher.
lib/article_screen.dart
class _ArticleScreenState extends State<ArticleScreen> {
...
floatingActionButton: FloatingActionButton.extended(
onPressed: () async {
if (_globalKey.currentContext != null) {
var path = await HomeWidget.renderFlutterWidget(
LineChart(),
fileName: 'screenshot',
key: 'filename',
logicalSize: _globalKey.currentContext!.size,
pixelRatio:
MediaQuery.of(_globalKey.currentContext!).devicePixelRatio,
);
setState(() {
imagePath = path as String?;
});
}
updateHeadline(widget.article);
},
...
}
iOS-Code aktualisieren
Aktualisieren Sie für iOS den Code, um den Dateipfad aus dem Speicher abzurufen und die Datei als Bild mit SwiftUI anzuzeigen.
Öffnen Sie die Datei NewsWidgets.swift, um die folgenden Änderungen vorzunehmen:
Fügen Sie filename und displaySize zum NewsArticleEntry-struct hinzu.
Die Eigenschaft filename enthält den String, der den Pfad zur Bilddatei darstellt. Die Eigenschaft displaySize enthält die Größe des Startbildschirm-Widgets auf dem Gerät des Nutzers. Die Größe des Startbildschirm-Widgets wird aus context abgerufen.
ios/NewsWidgets/NewsWidgets.swift
struct NewsArticleEntry: TimelineEntry {
...
// New: add the filename and displaySize.
let filename: String
let displaySize: CGSize
}
Aktualisieren Sie die placeholder-Funktion.
Fügen Sie die Platzhalter filename und displaySize ein.
ios/NewsWidgets/NewsWidgets.swift
func placeholder(in context: Context) -> NewsArticleEntry {
NewsArticleEntry(date: Date(), title: "Placeholder Title", description: "Placeholder description", filename: "No screenshot available", displaySize: context.displaySize)
}
Rufen Sie den Dateinamen aus userDefaults in getSnapshot ab.
Dadurch wird die Variable filename auf den Wert filename im Speicher userDefaults gesetzt, wenn das Startbildschirm-Widget aktualisiert wird.
ios/NewsWidgets/NewsWidgets.swift
func getSnapshot(
...
let title = userDefaults?.string(forKey: "headline_title") ?? "No Title Set"
let description = userDefaults?.string(forKey: "headline_description") ?? "No Description Set"
// New: get fileName from key/value store
let filename = userDefaults?.string(forKey: "filename") ?? "No screenshot available"
...
)
ChartImage erstellen, das das Bild aus einem Pfad anzeigt
In der Ansicht ChartImage wird ein Bild aus dem Inhalt der Datei erstellt, die auf der Dart-Seite generiert wurde. Hier legen Sie die Größe auf 50% des Frames fest.
ios/NewsWidgets/NewsWidgets.swift
struct NewsWidgetsEntryView : View {
...
// New: create the ChartImage view
var ChartImage: some View {
if let uiImage = UIImage(contentsOfFile: entry.filename) {
let image = Image(uiImage: uiImage)
.resizable()
.frame(width: entry.displaySize.height*0.5, height: entry.displaySize.height*0.5, alignment: .center)
return AnyView(image)
}
print("The image file could not be loaded")
return AnyView(EmptyView())
}
...
}
Verwenden Sie das ChartImage im Text von NewsWidgetsEntryView.
Fügen Sie die ChartImage-Ansicht in den Hauptteil der NewsWidgetsEntryView ein, um das ChartImage im Startbildschirm-Widget anzuzeigen.
ios/NewsWidgets/NewsWidgets.swift
VStack {
Text(entry.title).font(Font.custom("Chewy", size: 13))
Text(entry.description).font(.system(size: 12)).padding(10)
// New: add the ChartImage to the NewsWidgetEntryView
ChartImage
}
Änderungen testen
Um die Änderungen zu testen, führen Sie sowohl das Ziel Ihrer Flutter-App (Runner) als auch das Ziel Ihrer Erweiterung in Xcode noch einmal aus. Um das Bild zu sehen, rufen Sie eine der Artikelseiten in der App auf und drücken Sie die Schaltfläche zum Aktualisieren des Startbildschirm-Widgets.

Android-Code aktualisieren
Der Android-Code funktioniert genauso wie der iOS-Code.
- Öffnen Sie die Datei
android/app/res/layout/news_widget.xml. Es enthält die UI-Elemente Ihres Startbildschirm-Widgets. Ersetzen Sie den Inhalt durch folgenden Code:
android/app/res/layout/news_widget.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/widget_container"
style="@style/Widget.Android.AppWidget.Container"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@android:color/white"
android:theme="@style/Theme.Android.AppWidgetContainer">
<TextView
android:id="@+id/headline_title"
style="@style/Widget.Android.AppWidget.InnerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:background="@android:color/white"
android:text="Title"
android:textSize="20sp"
android:textStyle="bold" />
<TextView
android:id="@+id/headline_description"
style="@style/Widget.Android.AppWidget.InnerView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/headline_title"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="4dp"
android:background="@android:color/white"
android:text="Title"
android:textSize="16sp" />
<!--New: add this image view -->
<ImageView
android:id="@+id/widget_image"
android:layout_width="200dp"
android:layout_height="200dp"
android:layout_below="@+id/headline_description"
android:layout_alignBottom="@+id/headline_title"
android:layout_alignParentStart="true"
android:layout_alignParentLeft="true"
android:layout_marginStart="8dp"
android:layout_marginLeft="8dp"
android:layout_marginTop="6dp"
android:layout_marginBottom="-134dp"
android:layout_weight="1"
android:adjustViewBounds="true"
android:background="@android:color/white"
android:scaleType="fitCenter"
android:src="@android:drawable/star_big_on"
android:visibility="visible"
tools:visibility="visible" />
</RelativeLayout>
Mit diesem neuen Code wird dem Startbildschirm-Widget ein Bild hinzugefügt, das (vorerst) ein allgemeines Sternsymbol enthält. Ersetzen Sie dieses Sternsymbol durch das Bild, das Sie im Dart-Code gespeichert haben.
- Öffnen Sie die Datei
NewsWidget.kt. Ersetzen Sie den Inhalt durch den folgenden Code:
android/app/java/com.mydomain.homescreen_widgets/NewsWidget.kt
// Import will depend on App ID.
package com.mydomain.homescreen_widgets
import android.appwidget.AppWidgetManager
import android.appwidget.AppWidgetProvider
import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.widget.RemoteViews
import java.io.File
import es.antonborri.home_widget.HomeWidgetPlugin
/**
* Implementation of App Widget functionality.
*/
class NewsWidget : AppWidgetProvider() {
override fun onUpdate(
context: Context,
appWidgetManager: AppWidgetManager,
appWidgetIds: IntArray,
) {
for (appWidgetId in appWidgetIds) {
val widgetData = HomeWidgetPlugin.getData(context)
val views = RemoteViews(context.packageName, R.layout.news_widget).apply {
val title = widgetData.getString("headline_title", null)
setTextViewText(R.id.headline_title, title ?: "No title set")
val description = widgetData.getString("headline_description", null)
setTextViewText(R.id.headline_description, description ?: "No description set")
// New: Add the section below
// Get chart image and put it in the widget, if it exists
val imageName = widgetData.getString("filename", null)
val imageFile = File(imageName)
val imageExists = imageFile.exists()
if (imageExists) {
val myBitmap: Bitmap = BitmapFactory.decodeFile(imageFile.absolutePath)
setImageViewBitmap(R.id.widget_image, myBitmap)
} else {
println("image not found!, looked @: ${imageName}")
}
// End new code
}
appWidgetManager.updateAppWidget(appWidgetId, views)
}
}
}
Mit diesem Dart-Code wird ein Screenshot mit dem Schlüssel filename im lokalen Speicher gespeichert. Außerdem wird der vollständige Pfad des Bildes abgerufen und daraus ein File-Objekt erstellt. Wenn das Bild vorhanden ist, wird es im Startbildschirm-Widget durch das neue Bild ersetzt.
- Laden Sie Ihre App neu und rufen Sie einen Artikelbildschirm auf. Drücken Sie auf Startbildschirm aktualisieren. Das Diagramm wird im Startbildschirm-Widget angezeigt.
7. Nächste Schritte
Glückwunsch!
Herzlichen Glückwunsch! Sie haben erfolgreich Startbildschirm-Widgets für Ihre Flutter-Apps für iOS und Android erstellt.
Verlinken von Inhalten in Ihrer Flutter-App
Je nachdem, wo der Nutzer klickt, möchten Sie ihn möglicherweise auf eine bestimmte Seite in Ihrer App weiterleiten. In der Nachrichten-App aus diesem Codelab soll der Nutzer beispielsweise den Nachrichtenartikel für die angezeigte Überschrift sehen.
Diese Funktion wird in diesem Codelab nicht behandelt. Beispiele für die Verwendung eines Streams, der vom home_widget-Paket bereitgestellt wird, um App-Starts über Startbildschirm-Widgets zu erkennen und Nachrichten über die URL vom Startbildschirm-Widget aus zu senden. Weitere Informationen finden Sie in der Dokumentation zu Deeplinks auf docs.flutter.dev.
Widget im Hintergrund aktualisieren
In diesem Codelab haben Sie ein Update des Startbildschirm-Widgets über eine Schaltfläche ausgelöst. Das ist zwar für Tests sinnvoll, aber im Produktionscode sollte die App das Startbildschirm-Widget im Hintergrund aktualisieren. Mit dem Workmanager-Plug-in können Sie Hintergrundaufgaben erstellen, um Ressourcen zu aktualisieren, die das Startbildschirm-Widget benötigt. Weitere Informationen finden Sie im Abschnitt Background update im Paket „home_widget“.
Unter iOS kann das Startbildschirm-Widget auch eine Netzwerkanfrage senden, um die Benutzeroberfläche zu aktualisieren. Über die Zeitachse können Sie die Bedingungen oder die Häufigkeit dieser Anfrage steuern. Weitere Informationen zur Verwendung der Zeitachse finden Sie in der Dokumentation von Apple zum Aktualisieren von Widgets .