İçeriğe geç / Skip to content / Zum Inhalt
Ahmet Balaman LogoAhmet Balaman

Flutter: Eigene Widgets erstellen

Ahmet Balaman
FlutterWidgetStatelessWidgetStatefulWidgetConstructor

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?

  1. Codewiederholung vermeiden: Dieselbe Struktur an verschiedenen Stellen nutzen
  2. Lesbarkeit: Komplexe Strukturen mit einfachen Namen ausdrücken
  3. Einfache Wartung: Änderungen an einer einzigen Stelle vornehmen
  4. 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

  1. Verwenden Sie const-Konstruktoren:
const MyWidget({Key? key}) : super(key: key);
  1. Vergeben Sie sprechende Namen:
// ✅ Good
class UserProfileCard extends StatelessWidget { ... }

// ❌ Bad
class Widget1 extends StatelessWidget { ... }
  1. Prinzip der einzigen Verantwortung:
    Jedes Widget sollte genau eine Aufgabe erfüllen.

  2. 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 StatelessWidget oder StatefulWidget ab
  • Nimmt Parameter über den Konstruktor entgegen
  • Pflichtparameter werden mit required gekennzeichnet
  • Standardwerte können vergeben werden
  • Mit dem Parameter child entstehen 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!

Kommentare