Nella precedente lezione, abbiamo mosso i primi passi nella definizione di multi-child layout attraverso l’uso di Row
e Column
. Questi però non sono gli unici widget definiti da Flutter per creare interfacce complesse. Tra essi, infatti, c’è lo Stack Widget
che permette la sovrapposizione di più widget su layer differenti.
In questa lezione ci focalizzeremo proprio su questo componente attraverso alcuni esempi pratici, per meglio cogliere gli aspetti fondamentali e gli utilizzi di questo widget.
Stack Widget
Analogamente a quanto visto finora, lo Stack
widget può contenere molteplici widget figli che si trovano, a differenza dei widget Row
e Column
, su livelli differenti, componendo una vera e propria pila di elementi. Questo componente è quindi molto utile quando vogliamo sovrapporre diversi widget per creare interfacce nuove e articolate.
In uno Stack widget:
- il primo widget nella lista dei widget figli è quello di base;
- i widget figli successivi al primo sono sovrapposti al primo e tra loro, posizionandosi su layer differenti;
- non è possibile effettuare lo scroll dei widget figli;
- è possibile ritagliare i nodi figli che superano il box di rendering definito evitando effetti visivi poco gradevoli.
Uno degli aspetti particolari di questo questo widget è la possibilità di collocare i widget figli in una specifica posizione in base alla definizione o meno del widget Positioned
Stack
Positioned
Proprietà | Tipo Accettato | Descrizione |
---|---|---|
bottom
|
double
|
rappresenta la distanza tra il bordo inferiore del nodo figlio e la parte inferiore dello Stack
|
child
|
Widget
|
il widget da inserire nello Stack
|
height
|
double
|
l’altezza del nodo figlio |
left
|
double
|
rappresenta la distanza tra il bordo sinistro del nodo figlio e il lato sinistro dello Stack
|
right
|
double
|
rappresenta la distanza tra il il bordo destro del nodo figlio e il lato destro dello Stack
|
top
|
double
|
rappresenta la distanza tra il bordo superiore del nodo figlio e la parte superiore dello Stack
|
width
|
double
|
la larghezza del nodo figlio |
Attraverso queste proprietà è facile definire la posizione dei widget che devono essere messi nella pila. Tutti i widget racchiusi in un Positioned
Stack
positioned child
È bene precisare che non è obbligatorio usare il Positioned
Stack
alignment
non-positioned child
Infine, indipendentemente dalla posizione dei widget, la dimensione dello Stack
Le proprietà
Come tutti i widget che abbiamo visto in queste lezioni, lo Stack
widget fornisce poche ma utili proprietà per organizzare la pila di widget da mostrare. Tra queste abbiamo:
Proprietà | Tipo Accettato | Descrizione |
---|---|---|
alignment
|
AlignmentGeometry
|
come allineare i non-positioned child |
children
|
List<Widget>
|
racchiude la lista di componenti da visualizzare nella pila |
fit
|
StackFit
|
come devono essere dimensionati nella pila i non-positioned child. Ciò è reso possibile dall’utilizzo delle proprietà del widget StackFit
|
overflow
|
Overflow
|
utilizza le proprietà del widget Overflow
Stack
Overflow.clip
Stack
|
textDirection
|
TextDirection
|
la direzione del testo |
Vediamo adesso qualche esempio pratico di utilizzo per poter sfruttare al meglio gli Stack
Esempi pratici
Per iniziare, creiamo un nuovo progetto come mostrato in una precedente lezione di questa guida e, lasciando inalterati gli import
, il metodo main()
e la classe MyApp
, cancelliamo il resto per aggiungere il seguente StatelessWidget
, composto da uno Scaffold
per la definizione dell’AppBar
e di una SingleChildScrollView
(di cui abbiamo già parlato nella lezione 11) che conterrà tutti i nostri esempi pratici di import delle immagini.
class MyPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Lesson 16'),
),
body: SingleChildScrollView(
child: Column(
children: <Widget>[
//we will add our widgets here.
],
)),
);
}
}
Modifichiamo infine la classe MyApp
per impostare il widget appena creato come home.
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
// . . .
home: MyPage(),
);
}
}
Ora siamo pronti per le nostre sperimentazioni.
Vediamo da subito un semplice esempio di utilizzo immaginando di voler creare un Stack
composto da tre diversi Container
di diverse dimensioni e senza una specifica posizione. Inseriamo inoltre lo Stack
all’interno di un altro Container
.
Container(
margin: EdgeInsets.only(top: 10),
child: Stack(
children: <Widget>[
// Max Size
Container(
color: Colors.orange,
height: 300,
width: 300,
),
Container(
color: Colors.yellowAccent,
height: 200.0,
width: 200.0,
),
Container(
color: Colors.greenAccent,
height: 100.0,
width: 100.0,
)
],
)),
Eseguendo l’app, possiamo notare che tutti e tre gli elementi sono posizionati nell’angolo in alto a sinistra della schermata e, grazie alla differenza di dimensioni, è possibile vedere i diversi Container

Per ovviare a questo problema possiamo sfruttare la proprietà alignment
Stack
Container(
margin: EdgeInsets.only(top: 10),
child: Stack(
alignment: Alignment.centerRight,
children: <Widget>[
Container(
color: Colors.orange,
height: 300,
width: 300,
),
Container(
color: Colors.yellowAccent,
height: 200.0,
width: 200.0,
),
Container(
color: Colors.greenAccent,
height: 100.0,
width: 100.0,
)
],
),
),
Eseguendo l’app, possiamo vedere che impostando la proprietà a Alignment.centerRight
Stack
Container

Una volta visto come disporre lo Stack
Stack
Stack
- utilizzare il widget
Align
- utilizzare il widget
Positioned
Vediamo come utilizzare entrambe le opzioni.
Prendiamo in considerazione il primo esempio mostrato in questa lezione e modifichiamo le dimensioni dei widget. Prendiamo l’ultimo Container
dello Stack
e incapsuliamolo all’interno dell’Align
widget. Impostiamo inoltre la proprietà alignment
a Alignment.topRight
per posizionare il nostro elemento in alto a destra nello Stack
.
Align(
alignment: Alignment.topRight,
child: Container(
color: Colors.greenAccent,
height: 100.0,
width: 100.0,
)
)
Il risultato di questa modifica è visibile nella seguente immagine.

Nonostante l'uso di Align
Container
Positioned
Analogamente a quanto fatto prima, incapsuliamo l’ultimo widget all’interno del widget Positioned
right
top
Container
Positioned(
right: 50.0,
top: 60.0,
child: Container(
color: Colors.greenAccent,
height: 100.0,
width: 100.0,
)
)
Questa modifica ci permette di avere il risultato mostrato nella seguente figura e un maggiore controllo sul posizionamento dell’elemento nello Stack

Vediamo invece adesso come utilizzare la proprietà fit
Stack
fit
Stack
Widget _setFitStack(fit) => Stack(
fit: fit,
children: [
Container(
color: Colors.greenAccent,
height: 100.0,
width: 100.0,
)
],
);
Usiamo quindi questa funzione con i tre possibili valori che abbiamo a disposizione per la proprietà fit
Valore | Descrizione |
---|---|
loose
|
rende i widget figli più piccoli possibile all’interno dello Stack
|
expand
|
imposta la dimensione dei widget figli alla più grande possibile |
passthrough
|
il comportamento dipende dal nodo padre in cui è definito lo Stack
|
Invochiamo quindi la funzione all’interno del nostro codice come segue.
Container(
constraints: BoxConstraints.expand(height: 160),
child: _setFitStack(StackFit.loose),
),
Container(
constraints: BoxConstraints.expand(height: 160),
child: _setFitStack(StackFit.expand),
),
Container(
color: Colors.black,
alignment: Alignment.center,
child: _setFitStack(StackFit.passthrough),
),
Come si può osservare, il metodo privato che abbiamo definito viene invocato all’interno di un apposito Container
widget di cui vengono impostati dei vincoli di altezza per i primi due widget, mentre per il terzo Container
sono state impostate alcune proprietà. Eseguendo quindi l’app, otterremo il seguente risultato.
È interessante notare come nel caso del valore loose
Container
passthrough
Container
Vediamo infine la proprietà overflow
Stack
Definiamo quindi una semplice funzione che, data la proprietà overflow
Container
Stack
Text
overflow
Widget _setOverflowStack(overflow) => Container(
margin: EdgeInsets.only(top: 10),
color: Colors.yellow[800],
constraints: BoxConstraints.expand(height: 38),
child: Stack(
overflow: overflow,
children: <Widget>[
Positioned(
top: 10,
child: Text(
"cogito ergo sum, cogito ergo sum, cogito ergo sum, cogito ergo sum,\ncogito ergo sum, cogito ergo sum",
style: TextStyle(color: Colors.black, fontSize: 15),
),
)
],
),
);
Invochiamo quindi il metodo appena scritto passando come parametro il valore Overflow.visible
Overflow.clip

Come si può notare, nel primo caso il testo fuoriesce dallo Stack
Container
Compreso come usare le diverse proprietà, vediamo come creare uno Stack
Per fare ciò, dovremo creare uno Stack
- un
CircleAvatar
- un
Container
Text
Creiamo quindi un semplice metodo generico che, dato in ingresso il percorso dell’immagine e il nome dell’utente, restituirà uno Stack
widget come quello poc’anzi descritto.
Widget _buildStack(pic, name) => Stack(
alignment: const Alignment(0.6, 0.6),
children: [
CircleAvatar(
backgroundImage: AssetImage(pic),
radius: 100,
),
Container(
decoration: BoxDecoration(
color: Colors.black45,
),
child: Text(
name,
style: TextStyle(
fontSize: 20,
fontWeight: FontWeight.bold,
color: Colors.white,
),
),
),
],
);
In questo caso, andiamo a invocare il metodo appena creato passando come nome da mostrare e immagine quelli che abbiamo a disposizione nella cartella assets specificata nel pubspec.yaml (vedi lezione 12 per maggiori dettagli). Inoltre, per motivi grafici centriamo il widget come segue.
Center(
child: _buildStack('girl.jpg', 'Shawna'),
)
Eseguendo l’app otterremo il seguente risultato.

Il codice di questa lezione è disponibile su GitHub