betacode

Руководство Flutter Row

View more Tutorials:

Следуйте за нами на нашей фан-странице, чтобы получать уведомления каждый раз, когда появляются новые статьи. Facebook

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

View more Tutorials:

Maybe you are interested

Это онлайн курс вне вебсайта o7planning, который мы представляем, он включает бесплатные курсы или курсы со скидкой.