Flutter: ein eigenes Widget erstellen und einbinden


Wenn man sich mit Flutter beschäftigt, stößt man früher oder später an Grenzen.
Dabei meine ich jetzt nicht eine spezifische Problemstellung, sondern vielmehr die Strukturierung und die Organisation des eigenen Codes.
Das mag einem geübten, professionellen Programmierer nur ein müdes Lächeln entlocken. Menschen die programmieren lernen, ob jetzt aus beruflichen Gründen, oder aus Spaß an der Sache, eher weniger.


In diesem Post schauen wir uns deshalb, die Möglichkeit an ein Custom Widget zu verwenden.

Starter Code

 Über die letzten Artikel habe ich den Starter Code eigentlich nicht mehr verändert. Er dient als Anker für die Demo Widgets die ich erstelle, um Flutter zu testen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
import 'package:flutter/material.dart';
import 'package:flutter/rendering.dart';
import 'package:tutflutter_002/meine_widgets.dart';

void main() {
  debugPaintSizeEnabled=false;
  runApp(MeinDemo());
}

class MeinDemo extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: "Mein Demo",
      theme:ThemeData(
        primaryColor: Colors.black,
      ),
      home: MeineHomePage2(),
    );
  }
}

Wenn sich der Leser mit Flutter schon ein wenig beschäftigt hat, sollte ihm der Code oben nichts neues zu bieten haben. MeineHomePage2() ist das Demo Widget das wir verwenden und weiter entwickeln werden. material.dart importieren wir im Moment grundsätzlich, rendering.dart gibt uns Zugriff auf gewisse Debugg Features für das Layout und meine_widgets.dart enthält unsere Demo Widgets.
Wie an anderer Stelle in diesem Blog schon geschrieben, für jedes Demo ein neues Projekt anzulegen ist übertrieben. Man füllt so nur die Festplatte, obwohl sich am Code nicht viel ändert und es ja "nur" zum lernen gedacht ist. Hier der Code für das Haupt Widget in seinem Startzustand:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class _MeineHomePage2State extends State<MeineHomePage2> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Widget Demo"),
      ),
      body: Container(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Center(
              child: Card(
                child: Column(
                  children: <Widget>[
                    Text("fluttercode Demo",
                    style: TextStyle(
                      fontFamily: "Anton",
                      fontSize: 32,
                    ),
                    )
                  ],
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

Der Code oben ist keine Sensation: Wie üblich arbeiten wir mit einem Scaffold(...) und einer AppBar(...). Als generellen Behälter für den View fungiert ein Container(...), der als Kind eine Column(...) hat. Innerhalb dieser Column zentrieren wir mit Center(...) eine Card(...).
Diese selbst hat wieder eine Column(...), deren einziges Kind im Moment ein Text(...) ist.

Wenn wir den Code genau betrachten sehen wir, das Container, Column, Center im Prinzip reine Layout Widgets sind. Sie strukturieren den eigentlichen Inhalt. Card wiederum kann man zwar auch als Layout Widget betrachten, der Einsatzzweck ist aber um einiges spezifischer.

Card ist dazu gedacht Informationen darzustellen, die miteinander in einem Zusammenhang stehen. Eine Adresse ist zum Beispiel ein Satz von Daten, der in einem Zusammenhang steht.

unsere eigene Card

Als erstes erstellen wir uns ein allein stehendes Card Widget:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
class MeineCard extends StatefulWidget {
  final Widget kind;

  MeineCard({Key key,@required this.kind}) : super (key:key);

  @override
  _MeineCardState createState() => _MeineCardState();
}

class _MeineCardState extends State<MeineCard> {
  @override
  Widget build(BuildContext context) {
    return Container(
      child: widget.kind,
    );
  }
}

Dieser Code oben ist nun schon anspruchsvoller zu verstehen. Im Haupt Widget MeineHomePage2(...) hatten wir ja schon ein Card Widget Eintrag. Dieser hatte eine Column als child und einen Text(...) als children: .
Im Code oben definieren wir mit final Widget kind; unser Widget darauf vor, das es ein Kind übergeben bekommt. child: widget.kind, sorgt dafür das das übergebene Kind im Container eingebetet wird. Schauen wir uns die Stelle im Haupt Widget an die wir abändern müssen:


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
 child: MeineCard(
                kind: Column(
                  children: <Widget>[
                    Text("fluttercode Demo",
                    style: TextStyle(
                      fontFamily: "Anton",
                      fontSize: 32,
                    ),
                    )
                  ],
                ),
              ),

Aus child:Card(...) wurde child: MeineCard(...). Statt child: Column(...) heisst es nun kind: Column(...). Der Rest des Codes ist unverändert.

Wer den Code aufmerksam gelesen hat, wird festgestellt haben, das die Card verschwunden ist. MeineCard(...) retourniert einen Container(...) und dieser erhält dann im Haupt Widget eine Column(...) als child: . Jetzt ändern wir MeineCard(...) noch einmal ab um auch wirklich eine Card zurück zu bekommen:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
class MeineCard extends StatefulWidget {
  final Widget kind;

  MeineCard({Key key,@required this.kind}) : super (key:key);

  @override
  _MeineCardState createState() => _MeineCardState();
}

class _MeineCardState extends State<MeineCard> {
  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 8.0,
      child: Container(
        padding: EdgeInsets.all(10.0),
        child: widget.kind,
      ),
    );
  }
}

Im Code oben haben wir Column durch Card ersetzt. Dieser Card geben wir noch mit elevation: 8.0, einen Effekt mit auf den Weg. Als child: hat die Card einen Container. Dieser Container erlaubt es uns, zwischen dem Inhalt der Card und dem Rand der Card ein Padding zu definieren.  Zum Abschluss noch einmal der komplette Code und das Ergebnis. Bis bald !

Resultat


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
class MeineCard extends StatefulWidget {
  final Widget kind;

  MeineCard({Key key,@required this.kind}) : super (key:key);

  @override
  _MeineCardState createState() => _MeineCardState();
}

class _MeineCardState extends State<MeineCard> {
  @override
  Widget build(BuildContext context) {
    return Card(
      elevation: 8.0,
      child: Container(
        padding: EdgeInsets.all(10.0),
        child: widget.kind,
      ),
    );
  }
}

class MeineHomePage2 extends StatefulWidget {
  @override
  _MeineHomePage2State createState() => _MeineHomePage2State();
}

class _MeineHomePage2State extends State<MeineHomePage2> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Widget Demo"),
      ),
      body: Container(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Center(
              child: MeineCard(
                kind: Column(
                  children: <Widget>[
                    Text("fluttercode Demo",
                    style: TextStyle(
                      fontFamily: "Anton",
                      fontSize: 32,
                    ),
                    )
                  ],
                ),
              ),
            )
          ],
        ),
      ),
    );
  }
}

Hier noch das Ergebnis:

Dieses Beispiel wurde einem Video Tutorial entnommen (englisch) von Paul Halliday.
Dieses findet man hier !


Kommentare

Beliebte Posts aus diesem Blog

Dart Basic: abstract class Part 1

Flutter und JSON

Flutter -- Tutorial Teil 6 Provider Part 1