codestory

Die Anleitung zu Flutter Row

  1. Row
  2. children
  3. Add/Remove children
  4. mainAxisAlignment
  5. mainAxisSize
  6. crossAxisAlignment
  7. textDirection
  8. verticalDirection
  9. textBaseline

1. Row

Row ist ein Widget, das seine untergeordneten Widgets in einer Zeile anzeigt. Eine andere Variante ist Column, bei der die untergeordneten Widgets in einer Spalte angezeigt werden.
Damit die untergeordneten Widgets von Row erweitert wird, um den verfügbaren horizontalen Bereich auszufüllen, können Sie es in ein Objekt Expanded einschließen.
Row platziert seine untergeordneten Elemente in einer Zeile und kann nicht gescrollt werden. Wenn Sie einen ähnlichen und scrollbaren Container wünschen, sollten Sie ListView verwenden.
Row Constructor:
Row Constructor
Row(
    {Key key,
    List<Widget> children: const <Widget>[],
    MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start,
    MainAxisSize mainAxisSize: MainAxisSize.max,
    CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center,
    TextDirection textDirection,
    VerticalDirection verticalDirection: VerticalDirection.down,
    TextBaseline textBaseline: TextBaseline.alphabetic
    }
)

2. children

Das Property children wird verwendet, um eine Liste der untergeordneten Widgets von Row zu definieren.
Sie können untergeordneten Widgets zu children, oder Widgets aus der children entfernen. Sie müssen jedoch die im Abschnitt "Add/Remove Children" genannte Regel befolgen.
List<Widget> children: const <Widget>[]
Beginnen wir mit dem ersten Beispiel, einer Row mit vier untergeordneten Widgets:
main.dart (children ex1)
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'o7planning.org',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
          title: Text("Flutter Row Example")
      ),
      body: Center(
          child: Row (
              children: [
                ElevatedButton(child: Text("BTN 1"), onPressed:(){}),
                Icon(Icons.ac_unit, size: 64, color: Colors.blue),
                ElevatedButton(
                    child: Text("Button 2"),
                    onPressed:(){},
                    style: ButtonStyle(
                        minimumSize: MaterialStateProperty.all(Size.square(100))
                    )
                ),
                ElevatedButton(child: Text("BTN 3"), onPressed:(){}),
              ]
          )
      ),
    );
  }
}
Einige untergeordneten Widgets mit flex > 0 können ihre Breite erweitern, um den verbleibenden Bereich horizontal auszufüllen, z.B Expanded, Spacer, usw. Sie werden häufig verwendet, um den Abstand zwischen den untergeordneten Widgets von Row anzupassen. Hier ist ein Beispiel:
children (ex2)
Row (
    children: [
      ElevatedButton(child: Text("BTN 1"), onPressed:(){}),
      Expanded(
         flex: 1,
         child: Icon(Icons.ac_unit, size: 64, color: Colors.blue),
      ),
      ElevatedButton(
          child: Text("Button 2"),
          onPressed:(){},
          style: ButtonStyle(
              minimumSize: MaterialStateProperty.all(Size.square(100))
          )
      ),
      Spacer(
         flex: 2
      ),
      ElevatedButton(child: Text("BTN 3"), onPressed:(){}),
    ]
)

3. Add/Remove children

Sie können einer Row einige untergeordnete Widgets hinzufügen oder einige davon aus der Row entfernen. Und die folgende Ausführungsweise kann die unerwarteten Ergebnisse führen:
** Not Working! **
class SomeWidgetState extends State<SomeWidget> {
  List<Widget> _children;

  void initState() {
    _children = [];
  }

  void someHandler() {
    setState(() {
        _children.add(newWidget);
    });
  }

  Widget build(BuildContext context) {
    // Reusing `List<Widget> _children` here is problematic.
    return Row(children: this._children);
  }
}
Um das oben genannte Problem zu lösen, müssen Sie die folgenden Regeln einhalten:
  • Die untergeordneten Widgets muss explizit einen Wert Key zugewiesen werden, damit Flutter alte oder neue untergeordnete Widgets erkennt, wenn sich die Anzahl der Widgets ändert.
  • Ein neues Objekt List für Row.children erstellt werden, wenn sich ein bestimmtes untergeordnetes Widget ändert oder die Anzahl der untergeordneten Widgets.
** Worked! **
class SomeWidgetState extends State<SomeWidget> {
  List<Widget> _children;

  void initState() {
    this._children = [];
  }
 
  // Add or remove some children..
  void someHandler() {
    setState(() {
      // The key here allows Flutter to reuse the underlying render
      // objects even if the children list is recreated.
      this._children.add(newWidget(key: ...));
    });
  }

  Widget build(BuildContext context) {
    // Always create a new list of children as a Widget is immutable.
    var newChildren = List.from(this._children);
    this._children = newChildren;
    
    return Row(children: this._children);
  }
}
Zum Beispiel:
main.dart (children ex3)
import 'package:flutter/material.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'o7planning.org',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  State<StatefulWidget> createState() {
    return MyHomePageState();
  }
}


class MyHomePageState extends State<MyHomePage> {
  List<Widget> _children = [];
  int idx = 0;

  @override
  void initState()  {
    super.initState();

    this._children = [
      ElevatedButton(
          key: Key(this.idx.toString()),
          child: Text("Btn " + idx.toString()),
          onPressed: (){}
      )
    ];
  }

  void addChildHandler()  {
    this.idx++;
    this.setState(() {
      var newChild = ElevatedButton(
          key: Key(this.idx.toString()),
          child: Text("Btn " + idx.toString()),
          onPressed: (){}
      );
      this._children.add(newChild);
    });
  }

  @override
  Widget build(BuildContext context) {
    // Create new List object:

    this._children = this._children == null? [] : List.from(this._children);

    return Scaffold(
      appBar: AppBar(
          title: Text("Flutter Row Example")
      ),
      body: Center(
          child: Row (
              children:  this._children
          )
      ),
      floatingActionButton: FloatingActionButton(
          child: Icon(Icons.add),
          onPressed: ()  {
            this.addChildHandler();
          }
      ),
    );
  }
}

4. mainAxisAlignment

Mit dem Property mainAxisAlignment wird angegeben, wie die untergeordneten Widgets auf der Hauptachse angeordnet werden. Bei Row ist die Hauptachse die horizontale Hauptachse.
MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start

// MainAxisAlignment enum:
 
MainAxisAlignment.start
MainAxisAlignment.center
MainAxisAlignment.end

MainAxisAlignment.spaceBetween
MainAxisAlignment.spaceAround
MainAxisAlignment.spaceEvenly
MainAxisAlignment.start
Wenn textDirection = TextDirection.ltr (Standard) und mainAxisAlignment = MainAxisAlignment.start , wird die untergeordneten Widgets von Row von links nach rechts nebeneinander platziert.
MainAxisAlignment.start
Row (
    mainAxisAlignment: MainAxisAlignment.start,
    children: [
      ElevatedButton(child: Text("Button 1"), onPressed:(){}),
      ElevatedButton(
          child: Text("Button 2"),
          onPressed:(){},
          style: ButtonStyle(
              minimumSize: MaterialStateProperty.all(Size.square(100))
          )
      ),
      ElevatedButton(child: Text("Very Long Button 3"), onPressed:(){})
    ]
)
MainAxisAlignment.center
mainAxisAlignment: MainAxisAlignment.center
MainAxisAlignment.end
Falls textDirection = TextDirection.ltr (Standard) und mainAxisAlignment = MainAxisAlignment.end , werden die untergeordneten Widgets von Row von rechts nach links nebeneinander platziert
mainAxisAlignment: MainAxisAlignment.end
MainAxisAlignment.spaceBetween
mainAxisAlignment: MainAxisAlignment.spaceBetween
MainAxisAlignment.spaceEvenly
mainAxisAlignment: MainAxisAlignment.spaceEvenly
MainAxisAlignment.spaceAround
mainAxisAlignment: MainAxisAlignment.spaceAround

5. mainAxisSize

Das Property mainAxisSize gibt an, wie viel vertikaler Raum von Row belegt werden soll. Der Standardwert ist MainAxisSize.max. Das bedeutet, dass Row versucht, so viel horizontalen Raum wie möglich einzunehmen.
Wenn es ein untergeordnetes Widgets mit "flex > 0 && fit != FlexFit.loose" gibt, versucht Row so viel Speicherplatz wie möglich zu belegen, das unabhängig vom Wert von mainAxisSize ist.
Wenn mainAxisSize = MainAxisSize.min ist, hat Row eine ausreichende Breite für alle untergeordneten Widgets.
MainAxisSize mainAxisSize: MainAxisSize.max

// MainAxisSize enum:

MainAxisSize.max
MainAxisSize.min

6. crossAxisAlignment

Mit dem Property crossAxisAlignment wird angegeben, wie die untergeordneten Widgets auf der Querachse angeordnet werden. Bei Row ist die Querachse die vertikale Achse.
CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center

// CrossAxisAlignment enum:

CrossAxisAlignment.start
CrossAxisAlignment.end
CrossAxisAlignment.center
CrossAxisAlignment.baseline
CrossAxisAlignment.stretch
CrossAxisAlignment.start
Wenn verticalDirection = VerticalDirection.down (Standard) und crossAxisAlignment = CrossAxisAlignment.start sind, werden die untergeordneten Widgets von Row nahe dem oberen Rand von Row platziert.
CrossAxisAlignment.start
Row (
    crossAxisAlignment: CrossAxisAlignment.start,

    children: [
      ElevatedButton(child: Text("Button 1"), onPressed:(){}),
      ElevatedButton(
          child: Text("Button 2"),
          onPressed:(){},
          style: ButtonStyle(
              minimumSize: MaterialStateProperty.all(Size.square(100))
          )
      ),
      ElevatedButton(child: Text("Very Long Button 3"), onPressed:(){})
    ]
)
CrossAxisAlignment.center (Default).
crossAxisAlignment: CrossAxisAlignment.center
CrossAxisAlignment.end
Falls verticalDirection = VerticalDirection.down (Standard) und crossAxisAlignment = CrossAxisAlignment.end, werden die untergeordneten Widgets von Row nahe dem unteren Rand der Row platziert.
crossAxisAlignment: CrossAxisAlignment.end
CrossAxisAlignment.stretch
crossAxisAlignment: CrossAxisAlignment.stretch
CrossAxisAlignment.baseline
crossAxisAlignment: CrossAxisAlignment.baseline
Zum Beispiel:
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic

7. textDirection

Das Property textDirection gibt an, wie die untergeordneten Widgets von Row auf der Hauptachse (horizontale Achse) angeordnet werden und wie die Wörter "start" und "end" interpretiert werden.
TextDirection textDirection

// TextDirection enum:

TextDirection.ltr (Left to Right) (Default)
TextDirection.rtl (Right to Left)
Wenn textDirection = TextDirection.ltr (Standard), entspricht das Wort "start""left" und das Wort "end""right".
Umgekehrt wenn textDirection = TextDirection.rtl, entspricht das Wort "start""right" und "end""left".

8. verticalDirection

Das Property verticalDirection gibt an, wie die untergeordneten Widgets von Row auf der Querachse (vertikale Achse) angeordnet werden und wie die Wörter "start" und "end" interpretiert werden.
VerticalDirection verticalDirection: VerticalDirection.down

// VerticalDirection enum:

VerticalDirection.down (Default)
VerticalDirection.up
Falls verticalDirection = VerticalDirection.down (Standard), entspricht das Wort "start""top" und das Wort "end""bottom".
Umgekehrt wenn verticalDirection = VerticalDirection.up, entspricht das Wort "start""bottom" und das Wort "end""top".

9. textBaseline

Wenn Sie die untergeordneten Widgets basierend auf der Grundlinie ausrichten, gibt das Property textBaseline an, welche Art von Grundlinie verwendet wird.
TextBaseline textBaseline: TextBaseline.alphabetic

// TextBaseline enum:

TextBaseline.alphabetic  (Default)
TextBaseline.ideographic
Zum Beispiel:
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic

Anleitungen Flutter

Show More