betacode

Руководство 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 - это виджет, который отображает свои дочерние виджеты в строке. Другой вариант - Column, который отображает свои дочерние виджеты в столбце.
Чтобы расширить дочерний виджет Row для заполнения доступного горизонтального пространства, нужно завернуть его в объект Expanded.
Row помещает свои дочерние элементы в одну строку и не может быть прокручен. Если вам нужен похожий и прокручиваемый контейнер (container), вам следует рассмотреть возможность использования ListView.
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

Свойство children используется для определения списка дочерних виджетов Row.
Вы можете добавлять дочерние виджеты к children или удалять виджеты из children, но вы должны следовать правилу, упомянутому в разделе "Add/Remove Children".
List<Widget> children: const <Widget>[]
Давайте начнем с первого примера, Row с четырьмя дочерними виджетами:
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:(){}),
              ]
          )
      ),
    );
  }
}
Некоторые дочерние виджеты с flex > 0 способны расширять свою ширину для заполнения оставшегося пространства по горизонтали, например Expanded, Spacer и т. д. Они часто используются для регулировки расстояния между дочерними виджетами Row. Вот пример:
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

Вы можете добавлять несколько дочерних виджетов в Row или удалять некоторые из них из Row. Выполнение этого процесса нижеприведенным способомможет привести к неожиданным результатам:
** 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);
  }
}
Чтобы решить вышеописанную проблему, необходимо соблюдать следующие правила:
  • Дочерним виджетам необходимо явно присвоить Key-значение, которое помогает Flutter распознавать старые или новые дочерние виджеты по мере изменения количества виджетов.
  • Новый объект List должен быть создан для Row.children, если изменяется определенный дочерний виджет или количество дочерних виджетов.
** 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);
  }
}
Например:
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

Свойство mainAxisAlignment используется для указания того, как дочерние виджеты будут расположены на главной оси (main axis). Для Row, главная ось (main axis) - это горизонтальная ось.
MainAxisAlignment mainAxisAlignment: MainAxisAlignment.start

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

MainAxisAlignment.spaceBetween
MainAxisAlignment.spaceAround
MainAxisAlignment.spaceEvenly
MainAxisAlignment.start
В случае textDirection = TextDirection. ltr (по умолчанию) и mainAxisAlignment = MainAxisAlignment.start дочерние виджеты Row будут располагаться рядом друг с другом слева направо.
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
В случае textDirection = TextDirection.ltr (по умолчанию) и mainAxisAlignment = MainAxisAlignment.end дочерние виджеты строки будут располагаться рядом друг с другом справа налево.
mainAxisAlignment: MainAxisAlignment.end
MainAxisAlignment.spaceBetween
mainAxisAlignment: MainAxisAlignment.spaceBetween
MainAxisAlignment.spaceEvenly
mainAxisAlignment: MainAxisAlignment.spaceEvenly
MainAxisAlignment.spaceAround
mainAxisAlignment: MainAxisAlignment.spaceAround

5. mainAxisSize

Свойство mainAxisSize указывает, какое вертикальное пространство должен занимать Row. Его значение по умолчанию - MainAxisSize. max, что означает, что Row пытается занять как можно больше горизонтального пространства.
Если есть дочерний виджет с "flex > 0 && fit != FlexFit.loose", Row постарается занять как можно больше пространства независимо от значения mainAxisSize.
В противном случае, если mainAxisSize = MainAxisSize.min, Row будет иметь достаточную ширину для всех своих дочерних виджетов.
MainAxisSize mainAxisSize: MainAxisSize.max

// MainAxisSize enum:

MainAxisSize.max
MainAxisSize.min

6. crossAxisAlignment

Свойство crossAxisAlignment используется для указания того, как дочерние виджеты будут расположены на поперечной оси (cross axis). Для Row, поперечная ось (cross axis) - это вертикальная ось.
CrossAxisAlignment crossAxisAlignment: CrossAxisAlignment.center

// CrossAxisAlignment enum:

CrossAxisAlignment.start
CrossAxisAlignment.end
CrossAxisAlignment.center
CrossAxisAlignment.baseline
CrossAxisAlignment.stretch
CrossAxisAlignment.start
В случае verticalDirection = VerticalDirection.down (по умолчанию) и crossAxisAlignment = CrossAxisAlignment.start, дочерние виджеты Row будут размещены близко к верхнему краю Row.
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
В случае verticalDirection = VerticalDirection.down (по умолчанию) и crossAxisAlignment = CrossAxisAlignment.end, дочерние виджеты Row будут размещены близко к нижнему краю Row.
crossAxisAlignment: CrossAxisAlignment.end
CrossAxisAlignment.stretch
crossAxisAlignment: CrossAxisAlignment.stretch
CrossAxisAlignment.baseline
crossAxisAlignment: CrossAxisAlignment.baseline
Например:
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic

7. textDirection

Свойство textDirection определяет, как дочерние виджеты Row будут расположены на главной оси (горизонтальной оси) и как слова "start" и "end" будут интерпретироваться.
TextDirection textDirection

// TextDirection enum:

TextDirection.ltr (Left to Right) (Default)
TextDirection.rtl (Right to Left)
Если textDirection = TextDirection.ltr (по умолчанию), слово "start" будет соответствовать "left", а слово "end" будет соответствовать "right".
В противном случае, при textDirection = TextDirection.rtl, слово "start" будет соответствовать "right" и слово "end" будет соответствовать "left".

8. verticalDirection

Свойство verticalDirection определяет, как дочерние виджеты Row будут расположены на поперечной оси (вертикальной оси) и как слова "start" и "end" будут интерпретироваться.
VerticalDirection verticalDirection: VerticalDirection.down

// VerticalDirection enum:

VerticalDirection.down (Default)
VerticalDirection.up
В случае verticalDirection = VerticalDirection.down (по умолчанию), слово "start" будет соответствовать "top", а слово "end" будет соответствовать "bottom".
В противном случае, при verticalDirection = VerticalDirection.up, слово "start" будет соответствовать "bottom", а слово "end" будет соответствовать "top".

9. textBaseline

При выравнивании (align) дочерних виджетов на основе базовой линии (baseline) свойство textBaseline указывает, какой тип базовой линии будет использоваться.
TextBaseline textBaseline: TextBaseline.alphabetic

// TextBaseline enum:

TextBaseline.alphabetic  (Default)
TextBaseline.ideographic
Например:
crossAxisAlignment: CrossAxisAlignment.baseline,
textBaseline: TextBaseline.alphabetic

Pуководства Flutter

Show More