Flutter: Eigene Widgets erstellen
Eigene Widgets in Flutter erstellen
Wenn Sie in Flutter eigene Widgets erstellen, wird Ihr Code modularer, lesbarer und wiederverwendbar. Über Konstruktoren nehmen Sie Parameter entgegen und machen Ihre Widgets anpassbar.
Warum sollten wir eigene Widgets erstellen?
- Codewiederholung vermeiden: Dieselbe Struktur an verschiedenen Stellen nutzen
- Lesbarkeit: Komplexe Strukturen mit einfachen Namen ausdrücken
- Einfache Wartung: Änderungen an einer einzigen Stelle vornehmen
- Testbarkeit: Widgets einzeln testen
Live-Demo: eigene Widgets erstellen
Lernen Sie interaktiv, wie Sie eigene Widgets erstellen:
💡 Falls das Beispiel oben nicht lädt, klicken Sie auf DartPad, um es in einem neuen Tab auszuführen.
Eigenes Widget mit StatelessWidget
StatelessWidget wird für Widgets ohne Zustand verwendet, deren Zustand sich also nicht ändert.
Grundstruktur
class MyCustomWidget extends StatelessWidget {
const MyCustomWidget({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: EdgeInsets.all(16),
child: Text('My Custom Widget'),
);
}
}Verwendung
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: Center(
child: MyCustomWidget(),
),
),
);
}
}Parameter über den Konstruktor
Über den Konstruktor können Sie Parameter entgegennehmen und Ihr Widget anpassbar machen.
Einfache Parameter
class CustomButton extends StatelessWidget {
final String text;
final Color color;
final VoidCallback onPressed;
const CustomButton({
Key? key,
required this.text,
required this.color,
required this.onPressed,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return ElevatedButton(
onPressed: onPressed,
style: ElevatedButton.styleFrom(
backgroundColor: color,
padding: EdgeInsets.symmetric(horizontal: 24, vertical: 12),
),
child: Text(text),
);
}
}Verwendung
CustomButton(
text: 'Save',
color: Colors.blue,
onPressed: () {
print('Saved');
},
)Pflicht- und optionale Parameter
Pflichtparameter
class UserCard extends StatelessWidget {
final String name;
final String email;
const UserCard({
Key? key,
required this.name, // Required
required this.email, // Required
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Card(
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(name, style: TextStyle(fontWeight: FontWeight.bold)),
SizedBox(height: 4),
Text(email, style: TextStyle(color: Colors.grey)),
],
),
),
);
}
}Optionale Parameter
class CustomCard extends StatelessWidget {
final String title;
final String? subtitle; // Optional (nullable)
final Color color;
const CustomCard({
Key? key,
required this.title,
this.subtitle, // Optional
this.color = Colors.blue, // Default value
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Card(
color: color,
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(title, style: TextStyle(fontSize: 18)),
if (subtitle != null) // Show if exists
Text(subtitle!, style: TextStyle(fontSize: 14)),
],
),
),
);
}
}Verwendung:
CustomCard(title: 'Title') // No subtitle
CustomCard(
title: 'Title',
subtitle: 'Subtitle',
color: Colors.green,
)Widget-Komposition
Komplexe Widgets lassen sich in kleinere Teile zerlegen.
Beispiel: Karte für einen Blogartikel
class BlogPostCard extends StatelessWidget {
final String title;
final String author;
final String date;
final String excerpt;
const BlogPostCard({
Key? key,
required this.title,
required this.author,
required this.date,
required this.excerpt,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Card(
margin: EdgeInsets.all(8),
child: Padding(
padding: EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
_buildHeader(),
SizedBox(height: 12),
_buildTitle(),
SizedBox(height: 8),
_buildExcerpt(),
],
),
),
);
}
Widget _buildHeader() {
return Row(
children: [
CircleAvatar(
child: Text(author[0]),
),
SizedBox(width: 8),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(author, style: TextStyle(fontWeight: FontWeight.bold)),
Text(date, style: TextStyle(fontSize: 12, color: Colors.grey)),
],
),
],
);
}
Widget _buildTitle() {
return Text(
title,
style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
);
}
Widget _buildExcerpt() {
return Text(
excerpt,
style: TextStyle(color: Colors.grey[700]),
maxLines: 3,
overflow: TextOverflow.ellipsis,
);
}
}Best Practices
- Verwenden Sie const-Konstruktoren:
const MyWidget({Key? key}) : super(key: key);- Vergeben Sie sprechende Namen:
// ✅ Good
class UserProfileCard extends StatelessWidget { ... }
// ❌ Bad
class Widget1 extends StatelessWidget { ... }Prinzip der einzigen Verantwortung:
Jedes Widget sollte genau eine Aufgabe erfüllen.Schreiben Sie Dokumentation:
/// Card widget that displays user information.
///
/// [name] and [email] parameters are required.
/// [avatarUrl] parameter is optional.
class UserCard extends StatelessWidget { ... }Zusammenfassung
Eigene Widgets erstellen:
- Leitet von
StatelessWidgetoderStatefulWidgetab - Nimmt Parameter über den Konstruktor entgegen
- Pflichtparameter werden mit
requiredgekennzeichnet - Standardwerte können vergeben werden
- Mit dem Parameter
childentstehen flexible Widgets - Komplexe Strukturen werden durch Komposition vereinfacht
Vorteile:
- Vermeidet Codewiederholung
- Erhöht die Lesbarkeit
- Erleichtert die Wartung
- Verbessert die Testbarkeit
- Ermöglicht Wiederverwendung
Eigene Widgets zu erstellen ist in Flutter die Grundlage für sauberen und wartbaren Code. Überlegen Sie bei jeder sich wiederholenden Struktur, ob daraus ein Widget werden sollte!