Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial
  • Lezione 16 di 37
  • livello intermedio
Indice lezioni

Row e Column Widget: le fondamenta dei Multi-Child Layout

Un tutorial semplice e pratico che mostra come utilizzare i widget Row e Column per realizzare i layout di un'app mobile multipiattaforma con Flutter.
Un tutorial semplice e pratico che mostra come utilizzare i widget Row e Column per realizzare i layout di un'app mobile multipiattaforma con Flutter.
Link copiato negli appunti

Compreso il funzionamento di Flutter e dei suoi componenti base, iniziamo a compiere i primi passi per la creazione di layout più articolati per suddividere lo spazio della schermata in righe o colonne e per sovrapporre tra loro due widget.

In questa lezione vedremo nel dettaglio i widget Row e Column offerti da Flutter per la creazione di Multi-Child layout.

Row e Column Widget

Uno dei principali task nello sviluppo di un’app è quello di collocare correttamente gli elementi all’interno della schermata. Questo processo può avvenire in diversi modi, come ad esempio organizzare la schermata in righe e/o in colonne per disporre in modo appropriato gli elementi che contiene.

Per fare ciò, Flutter dispone dei widget Row e Cloumn, che risultano tra loro complementari e permettono l’organizzazione dei widget figli rispettivamente in righe e colonne. Nessuno dei due widget permette lo scroll orizzontale o verticale e qualora fosse necessario visualizzare un numero elevato di elementi è consigliabile usare una ListView.

Nel caso in cui non fosse noto a priori se usare una Row o una Column per la visualizzazione dei dati, Flutter mette a disposizione il widget Flex, che permette di controllare su quale asse (orizzontale o verticale) andare a disporre i figli. È consigliabile però sapere sempre come visualizzare i dati, in quanto l'uso di Flex può risultare eccessivamente verboso.

Infine, nel caso ci sia un solo elemento da visualizzare, invece di usare Flex, Row o Column è consigliabile utilizzare i widget Align o Center per posizionarlo nella schermata.

Le proprietà

A differenza degli altri widget definiti finora, composti da proprietà eterogenee, i widget Row e Column definiscono il medesimo set di proprietà, in quanto il primo è semplicemente una variante del secondo e viceversa. Tra le principali proprietà che è fondamentale conoscere ritroviamo:

Proprietà Tipo Accettato Descrizione
children List<Widget> è la lista di widget contenuti all’interno di questo componente e sottoalbero
crossAxisAlignment CrossAxisAlignment rappresenta come devono essere i widget figli posizionati lungo gli assi attraverso l’utilizzo delle proprietà offerte dal widget CrossAxisAlignment
direction Axis la direzione da utilizzare per l’asse principale. Per Row e Column questa proprietà è già fissata all’asse appropriato, ossia orizzontale per Row e verticale per Column
mainAxisAlignment MainAxisAlignment definisce come posizionare i widget figli attorno all’asse principale
mainAxisSize MainAxisSize rappresenta quanto spazio deve essere occupato nell’asse principale
textDirection TextDirection determina la disposizione dei widget figli orizzontalmente e come interpretare lo start e end nella direzione orizzontale
verticalDirection VerticalDirection fornisce la disposizione dei widget figli verticalmente e definisce come interpretare lo start e end nella direzione verticale

Comprese le proprietà di questi due widget simili tra loro, vediamo qualche esempio pratico.

Esempi pratici

Per iniziare, creiamo un nuovo progetto come mostrato nella lezione 6 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 da 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.

Partiamo subito da un semplice utilizzo di questi due widget.

Container(
  color: Colors.orange[100],
  child: Row(children: <Widget>[
    Text(
      "Text1",
      style: TextStyle(color: Colors.black, fontSize: 17),
    ),
    Text(
      "Text2",
      style: TextStyle(color: Colors.black, fontSize: 17),
    )
  ])),
// . . .
Container(
  color: Colors.orange[100],
  child: Column(children: <Widget>[
    Text(
      "Text1",
      style: TextStyle(color: Colors.black, fontSize: 17),
    ),
    Text(
      "Text2",
      style: TextStyle(color: Colors.black, fontSize: 17),
    )
  ])),

In questo caso, sia per il widget Row che Column abbiamo definito due Text che si dispongono in ordine lungo gli assi orizzontali e verticali, rispettivamente. In particolare, per rendere evidente l’effetto riga e colonna, abbiamo inserito i suddetti widget in appositi container di cui è stato definito il colore.

Eseguendo l’app otteniamo il risultato in figura.

Figura 98. Definizione dei widget Row e Column all’interno di appositi Container per a) Android e b) iOS (click per ingrandire)Definizione dei widget Row e Column all’interno di appositi Container

Passiamo adesso all’esplorazione della proprietà mainAxisAlignment.

Definiamo all’interno del nostro StatelessWidget un nuovo metodo che tornerà un oggetto di tipo Widget e che prende in ingresso il valore desiderato per mainAxisAlignment.

Widget _rowMainAlign(mainAxisAlignment) => Container(
    color: Colors.lightBlue[50],
    child: Row(
      mainAxisAlignment: mainAxisAlignment,
      children: <Widget>[
        Text(
          "Text1",
          style: TextStyle(color: Colors.black, fontSize: 17),
        ),
        Text(
          "Text2",
          style: TextStyle(color: Colors.black, fontSize: 17),
        ),
        Text(
          "Text3",
          style: TextStyle(color: Colors.black, fontSize: 17),
        ),
        Text(
          "Text4",
          style: TextStyle(color: Colors.black, fontSize: 17),
        ),
      ],
    ),
    height: 30,
    margin: EdgeInsets.all(5),
  );

In particolare, in questo metodo abbiamo definito un Container composto da un background colorato e avente come figlio un widget Row che presenta:

  • la proprietà mainAxisAlignment impostata al valore passato per parametro;
  • un lista di widget Text.

In questo modo, richiamando il metodo con le diverse proprietà fornite dal widget MainAxisAlignment potremo vedere il diverso comportamento di questa proprietà.

Ad esempio, impostando passando come parametro le proprietà MainAxisAlignment.start e MainAxisAlignment.center otteremo quanto segue.

Figura 99. Utilizzo della proprietà mainAxisAlignment usando i valori start e center per a) Android e b) iOS (click per ingrandire)Utilizzo della proprietà mainAxisAlignment usando i valori start e center per a) Android e b) iOS

In questo caso, gli elementi verranno spostati all’inizio o al centro della riga. Utilizzando le altre proprietà offerte da MainAxisAlignment otterremo il seguente risultato.

Figura 100. Diversi esempi di utilizzo della proprietà mainAxisAlignment per a) Android e b) iOS (click per ingrandire)Diversi esempi di utilizzo della proprietà mainAxisAlignment per a) Android e b) iOS

In particolare, è interessante porre l’attenzione sulle proprietà spaceBetween, spaceEvenly, e spaceAround che aggiungono uno spazio tra i widget figli della Row in modo differente, come si è potuto notare.

Prorpietà Descrizione
spaceBetween aggiunge uno spazio tra i widget figli spingendo il primo e l’ultimo elemento agli estremi
spaceEvenly aggiunge uno spazio prima e dopo i widget figli affinché esso sia uguale per tutti
spaceAround aggiunge uno spazio attorno ai widget che si somma nel caso di due widget vicini tra loro, aumentando la distanza

Similmente, possiamo ripetere lo stesso esperimento con il widget Column, scrivendo un metodo analogo (disponibile su GitHub).

Pertanto utilizzando le proprietà start, center ed end otterremo il seguente risultato.

Figura 101. Utilizzo della proprietà mainAxisAlignment con il widget Column per a) Android e b) iOS (click per ingrandire)Utilizzo della proprietà mainAxisAlignment con il widget Column per a) Android e b) iOS

Vediamo ora la proprietà crossAxisAlignment.

Come si è potuto notare, la proprietà mainAxisAlignment lavora orizzontalmente per le Row e verticalmente per le Column. La proprietà crossAxisAlignment è invece perpendicolare alla prima e quindi agirà verticalmente sulle Row e orizzontalmente sulle Column.

Figura 102. Relazione tra mainAxisAlignment e crossAxisAlignment (click per ingrandire)Relazione tra mainAxisAlignment e crossAxisAlignment

Vediamo un esempio di utilizzo tramite il widget Row. Definiamo un metodo che restituisca un nuovo widget Row composto da quattro widget Text e avente la proprietà crossAxisAlignment impostata al valore passato da parametro.

Widget _rowCrossAxisAlignment(crossAxisAlignment) => Container(
    color: Colors.lightGreen[50],
    child: Row(
      crossAxisAlignment: crossAxisAlignment,
      children: <Widget>[
        Text(
          "Text1",
          style: TextStyle(color: Colors.black, fontSize: 17),
        ),
        Text(
          "Text2",
          style: TextStyle(color: Colors.black, fontSize: 17),
        ),
        Text(
          "Text3",
          style: TextStyle(color: Colors.black, fontSize: 17),
        ),
        Text(
          "Text4",
          style: TextStyle(color: Colors.black, fontSize: 17),
        ),
      ],
    ),
    height: 50,
    margin: EdgeInsets.all(5),
  );

Invochiamo quindi il metodo appena scritto passando come parametro le proprietà di CrossAxisAlignment quali start, center ed end per ottenere il seguente risultato.

Figura 103. Utilizzo della proprietà crossAxisAlignment con il widget Row per a) Android e b) iOS (click per ingrandire)Utilizzo della proprietà crossAxisAlignment con il widget Row per a) Android e b) iOS

Come si può notare i quattro widget Text sono stati disposti in alto, al centro e in basso all’interno del container.

Analogamente, possiamo ripetere lo stesso esperimento con il widget Column scrivendo un metodo analogo e disponibile al seguente link.

Pertanto utilizzando le proprietà start, center ed end otterremo il seguente risultato.

Figura 104. Utilizzo della proprietà crossAxisAlignment con il widget Column per a) Android e b) iOS (click per ingrandire)Utilizzo della proprietà crossAxisAlignment con il widget Column per a) Android e b) iOS

Esaminiamo, adesso, la proprietà mainAxisAlignment.

Essa permette di definire la dimensione dell’asse principale di entrambi i widget. In particolare, possiamo assegnare a questa proprietà due valori:

Valore Descrizione
MainAxisAlignment.min assegna la minima dimensione possibile al widget, che sarà grande quanto la somma totale delle dimensioni dei suoi widget figli
MainAxisAlignment.max assegna la massima dimensione possibile al widget

Vediamo un semplice esempio con il widget Row, in quanto per il widget Column il comportamento sarà il medesimo ma sull’asse verticale.

Come già fatto in precedenza, definiamo un nuovo metodo che ritorna un Widget e prende come parametro di ingresso un valore per mainAxisSize.

Widget _rowMainAxisSize(mainAxisSize) => Container(
      color: mainAxisSize == MainAxisSize.min ? Colors.pink : Colors.yellowAccent,
      child: Row(
        mainAxisSize: mainAxisSize,
        children: <Widget>[
          Text(
            "Text1",
            style: TextStyle(color: Colors.black, fontSize: 17),
          ),
          Text(
            "Text2",
            style: TextStyle(color: Colors.black, fontSize: 17),
          ),
          Text(
            "Text3",
            style: TextStyle(color: Colors.black, fontSize: 17),
          ),
          Text(
            "Text4",
            style: TextStyle(color: Colors.black, fontSize: 17),
          ),
        ],
      ));

In particolare, questo metodo definisce quattro widget Text come figli della Row e imposta il mainAxisSize al valore passato per parametro.

Invocando perciò il metodo con i valori di min e max, otterremo quanto segue.

Figura 105. Utilizzo della proprietà mainAxisSize per il widget Row per a) Android e b) iOS (click per ingrandire)Utilizzo della proprietà mainAxisSize per il widget Row per a) Android e b) iOS

Chiudiamo infine questa sezione di esempi con l’utilizzo della proprietà verticalDirection.

Il comportamento cambia in base a quale widget usiamo e a quali proprietà sono definite. Per ulteriori dettagli rimandiamo alla documentazione ufficiale. In questa sede, ci limiteremo a mostrare un semplice esempio di utilizzo con Column.

Definiamo un nuovo metodo che ha come scopo quello di creare un widget Column e di impostare la verticalDirection passata da parametro.

Widget _columnVerticalDirection(verticalDirection) => Container(
        color: Colors.lightBlue[50],
        child: Column(
          verticalDirection: verticalDirection,
          children: <Widget>[
            Text(
              "Text1",
              style: TextStyle(color: Colors.black, fontSize: 17),
            ),
            Text(
              "Text2",
              style: TextStyle(color: Colors.black, fontSize: 17),
            ),
            Text(
              "Text3",
              style: TextStyle(color: Colors.black, fontSize: 17),
            ),
            Text(
              "Text4",
              style: TextStyle(color: Colors.black, fontSize: 17),
            ),
          ],
        ),
        height: 150,
        margin: EdgeInsets.all(5),
      );

Invochiamo ora il metodo passando come parametro il valore down e up di VerticalDirection ottenendo il risultato in figura.

Figura 106. Utilizzo della proprietà verticalDirection con un widget Column per a) Android e b) iOS (click per ingrandire)Utilizzo della proprietà verticalDirection con un widget Column per a) Android e b) iOS

In questo caso, con la proprietà down gli elementi vengono disposti dall’alto verso il basso, mentre con la proprietà up sono disposti dal basso verso l’alto.

Il codice di questa lezione è disponibile su GitHub.

Ti consigliamo anche