Контейнер Stack позволяет располагать одни элементы поверх других.
Для создания виджета Stack применяется следующий конструктор:
Stack({Key key, AlignmentGeometry alignment: AlignmentDirectional.topStart, TextDirection textDirection, StackFit fit: StackFit.loose, Overflow overflow: Overflow.clip, Clip clipBehavior: Clip.hardEdge, List<Widget> children: const <Widget>[]})
Его параметры:
key
: ключ виджета
alignment
: задает расположение вложенных виджетов
textDirection
: определяет порядок расположения вложенных элементов по горизонтали
fit
: определяет размеры для вложенных виджетов
overflow
: устанавливает, надо ли усекать вложенное содержимое
clipBehavior
: устанавливает, как вложенные элементы будут усекаться
children
: набор вложенных элементов
Определим виджет Stack, который будет содержать набор виджетов Container:
import 'package:flutter/material.dart'; void main() { runApp(Container( color: Colors.white, padding: EdgeInsets.only(top:40, bottom: 10, left: 20, right: 20), child: Stack( textDirection: TextDirection.ltr, children: <Widget>[ Container( width: 200, height: 200, color: Colors.blueGrey, ), Container( width: 160, height: 160, color: Colors.cyan, ), Container( width: 100, height: 100, color: Colors.blue, ), ], ) ) ); }
В данном случае Stack содержит три элемента Container, которые последовательно будут накладываться друг на друга.
Стоит отметить, что в этом случае также стоит задать свойство textDirection
По умолчанию вложенные виджеты располагаются в верхнем левом углу элемента Stack (по умолчанию для свойства
alignment установлено значение AlignmentDirectional.topStart
), но естественно с помощью свойства alignment,
которое представляет тип AlignmentGeometry
мы можем переопределить положение вложенных виджетов с помощью
одного из следующих значений:
AlignmentDirectional.topStart: выравнивание вверху в начале элемента (если ориентация текста - слева направо началом является левая граница, при ориентации текста справа налево началом является правая граница)
AlignmentDirectional.topEnd: выравнивание вверху в конце элемента (если ориентация текста - слева направо началом является правая граница, при ориентации текста справа налево началом является левая граница)
AlignmentDirectional.topCenter: выравнивание вверху по центру
AlignmentDirectional.bottomStart: выравнивание внизу в начале элемента
AlignmentDirectional.bottomEnd: выравнивание внизу в конце элемента
AlignmentDirectional.bottomCenter: выравнивание внизу по центру
AlignmentDirectional.center: выравнивание по горизонтали и по вертикали по центру.
Alignment.centerStart: выравнивание по центру в начале контейнера
Alignment.centerEnd: выравнивание по центру в конце контейнера
Например, расположим виджеты по центру:
import 'package:flutter/material.dart'; void main() { runApp(Container( color: Colors.white, padding: EdgeInsets.only(top:40, bottom: 10, left: 20, right: 20), child: Stack( alignment: AlignmentDirectional.center, textDirection: TextDirection.ltr, children: <Widget>[ Container( width: 240, height: 240, color: Colors.blueGrey, ), Container( width: 220, height: 220, color: Colors.black12, ), Text("Flutter на metanit.com", textDirection: TextDirection.ltr, softWrap: true, style: TextStyle(fontSize: 20), ), ], ) ) ); }
Выше в примерах расположение вложенных виджетов определялось свойством alignment. Но кроме этого мы можем с помощью виджета Positioned явным образом задать расположение для каждого вложенного элемента.
Для создания этого виджета использовать один из следующих конструкторов:
Positioned.directional({Key key, @required TextDirection textDirection, double start, double top,
double end, double bottom, double width, double height, @required Widget child})
:
определяет расположение вложенного виджета с помощью установки параметров:
start
: начало элемента (левая граница при направлении текста слева направо и правая граница при направлении
текста справа налево
end
: конец элемента (правая граница при направлении текста слева направо и левая граница при направлении
текста справа налево
top
: верхняя граница элемента
bottom
: нижняя граница элемента
width
: ширина вложенного элемента
height
: высота вложенного элемента
Positioned.fill({Key key, double left: 0.0, double top: 0.0, double right: 0.0, double bottom: 0.0, @required Widget child})
:
определяет расположение вложенного виджета с помощью установки параметров:
left
: левая граница элемента
right
: правая граница элемента
top
: верхняя граница элемента
bottom
: нижняя граница элемента
width
: ширина вложенного элемента
height
: высота вложенного элемента
Positioned.fromRect({Key key, Rect rect, @required Widget child})
:
расположение и размеры вложенные элемента задаются с помощью объекта Rect
Positioned.fromRelativeRect({Key key, RelativeRect rect, @required Widget child})
:
расположение и размеры вложенные элемента задаются с помощью объекта RelativeRect
Например, помести виджет Text в Positioned:
import 'package:flutter/material.dart'; void main() { runApp(Container( color: Colors.white, padding: EdgeInsets.only(top:40, bottom: 10, left: 20, right: 20), child: Stack( alignment: AlignmentDirectional.center, textDirection: TextDirection.ltr, children: <Widget>[ Container( width: 240, height: 240, color: Colors.blueGrey, ), Container( width: 220, height: 220, color: Colors.black12, ), Positioned( top: 50, left: 50, child: Text("Flutter на metanit.com", textDirection: TextDirection.ltr, softWrap: true, style: TextStyle(fontSize: 20, color: Colors.redAccent), ), ) , ], ) ) ); }
В данном случае виджет Text будет располагаться на 20 единиц вниз и вправо от верхней и левой границы контейнера Stack соответственно.
Свойство fit
определяет порядок заполнения контейнера Stack.
Оно принимает одно из значений перечисления StackFit:
StackFit.loose: вложенные виджеты принимают любые размеры, которые не превышают размеров контейнера.
Значение по умолчанию. Соответствует значению StackFit(0)/code>
StackFit.expand: вложенные виджеты принимают наибольшие доступные размеры. Соответствует значению StackFit(1)
Например, растянем вложенный виджет контейнер по всей длине и ширине контейнера Stack с помощью StackFit.expand
:
import 'package:flutter/material.dart'; void main() { runApp(Container( color: Colors.white, padding: EdgeInsets.only(top:40, bottom: 10, left: 20, right: 20), child: Stack( alignment: AlignmentDirectional.center, textDirection: TextDirection.ltr, fit: StackFit.expand, children: <Widget>[ Container( width: 240, height: 240, color: Colors.blueGrey, ), Container( width: 200, height: 200, color: Colors.redAccent, ) , ], ) ) ); }
Причем несмотря на то, что здесь два элемента Container, оба примут одну и ту же высоту и ширину, соответственно мы увидим только один виджет.