diegoRodicio

View Categories

📐 Espazos e distribución

Os widgets de distribución (layout) organizan o contido da pantalla. Os seguintes fragmentos poden colocarse no body dun Scaffold.

🎯 Centrar con Center

const Center(
  child: Text('IES San Mamede'), // Centrado no espazo dispoñible.
)

📏 Espazo arredor: Padding e EdgeInsets

Padding reserva espazo arredor do seu fillo. EdgeInsets indica canto espazo deixamos en cada lado.

const Padding(
  padding: EdgeInsets.all(16), // Deixamos 16 por cada lado.
  child: Text('2º DAM'),
)

ConstrutorEspazo que define
EdgeInsets.all(16)O mesmo en todos os lados.
EdgeInsets.symmetric(horizontal: 16, vertical: 8)Un valor para esquerda/dereita e outro para arriba/abaixo.
EdgeInsets.only(top: 8)Só nos lados indicados.
EdgeInsets.fromLTRB(8, 12, 8, 12)Esquerda, arriba, dereita e abaixo, nesta orde.

A seguinte captura ilustra o espazo que engade Padding arredor do texto.

Espazo interior arredor dun texto con Padding
Espazo interior arredor dun texto con Padding

🛡️ Protexer o contido con SafeArea

Nos móbiles, parte da pantalla pode estar ocupada pola barra de estado, o recorte da cámara ou o indicador de xestos inferior. SafeArea engade o espazo necesario para que o seu fillo non quede tapado por esas zonas, adaptándose ao dispositivo.

Con Padding indicamos nós canto espazo queremos; con SafeArea, Flutter calcula o espazo de seguridade. Podemos combinar ambos: un para protexer o contido e outro para que non quede pegado aos bordos.

Por exemplo, coloca este fragmento no body dun Scaffold:

const SafeArea(
  // Evitamos as zonas do dispositivo que poden tapar o contido.
  child: Padding(
    padding: EdgeInsets.all(16), // Engadimos unha marxe interior adicional.
    child: Text('Benvidos ao IES San Mamede · 2º DAM'),
  ),
)

Comparación da interface con e sen `SafeArea`
Comparación da interface con e sen SafeArea

O texto queda dentro da zona segura e, ademais, separado 16 unidades dos seus bordos. Nun dispositivo sen zonas que evitar, SafeArea pode non engadir espazo.

💡 Normalmente colocamos SafeArea arredor do contido que queremos protexer, non arredor de cada widget. Non resolve a falta de espazo cando o contido é demasiado grande: nese caso podemos necesitar desprazamento, como veremos coas listas.

📚 Consulta:

↔️ Filas e columnas: Row e Column

Row coloca os fillos en horizontal e Column, en vertical. Ambos reciben unha lista en children.

Nos exemplos, SizedBox(width: 16) deixa unha separación horizontal e SizedBox(height: 8), unha vertical. No seguinte apartado veremos tamén como usalo para dar tamaño a un widget.

const Row(
  mainAxisSize: MainAxisSize.min,
  children: [
    Icon(Icons.school, size: 32),
    SizedBox(width: 16),
    Icon(Icons.person, size: 32),
    SizedBox(width: 16),
    Icon(Icons.computer, size: 32),
  ],
)

const Column(
  mainAxisSize: MainAxisSize.min, // Ocupa só a altura que necesita.
  crossAxisAlignment: CrossAxisAlignment.start,
  children: [
    Text('Diego Rodicio'),
    SizedBox(height: 8),
    Text('Profesor de PMDM'),
  ],
)

PropiedadeEn RowEn Column
mainAxisAlignmentDistribúe en horizontal.Distribúe en vertical.
crossAxisAlignmentAliña en vertical.Aliña en horizontal.
mainAxisSizeDecide se intenta ocupar todo o ancho dispoñible (max) ou só o necesario (min).O mesmo, pero coa altura.

Para mainAxisAlignment, os valores máis útiles son start, center, end, spaceBetween e spaceEvenly. Os dous últimos reparten o espazo libre: entre os fillos ou tamén nos extremos.

Para crossAxisAlignment, comeza con start, center, end e stretch. stretch fai que os fillos ocupen o espazo dispoñible no eixe cruzado.

Na captura vemos unha fila de iconas e unha columna de textos dentro doutra columna.

Combinar unha fila de iconas e unha columna de textos
Combinar unha fila de iconas e unha columna de textos

↔️ Separar e dar tamaño con SizedBox

Sen fillo, SizedBox deixa un espazo baleiro. Usa height entre elementos dunha Column e width entre elementos dunha Row:

const Column(
  mainAxisSize: MainAxisSize.min,
  children: [
    Text('Diego Rodicio'),
    SizedBox(height: 16), // Separación vertical entre os dous textos.
    Text('2º DAM'),
  ],
)

Cun fillo, permite indicar o seu tamaño. Este fragmento pode ir no body:

const Center(
  child: SizedBox(
    width: 220,
    height: 100, // Tamaño da caixa que contén a tarxeta.
    child: Card(child: Center(child: Text('IES San Mamede'))),
  ),
)

Card mostra unha tarxeta e Center centra o texto dentro dela. O tamaño solicitado debe respectar o espazo que permite o pai; non sempre poderá ser exactamente o indicado. Estas medidas son píxeles lóxicos, unidades que Flutter adapta á densidade da pantalla.

Lembra: Padding deixa espazo arredor dun fillo; SizedBox separa widgets ou reserva un tamaño.

Separación e tamaño fixo mediante SizedBox
Separación e tamaño fixo mediante SizedBox

📚 Consulta:

🔲 Decorar con Container

Container permite combinar fondo, tamaño e espazos.

Container(
  width: 250, // Ancho do Container.
  height: 120, // Alto do Container.
  margin: const EdgeInsets.all(8), // Espazo exterior.
  padding: const EdgeInsets.all(16), // Espazo entre o bordo e o texto.
  color: Colors.blue.shade100,
  child: const Text('Diego Rodicio'),
)

Se só queremos espazo, adoita abondar con Padding ou SizedBox. Para bordos e esquinas redondeadas podemos usar decoration: BoxDecoration(...); nese caso, a cor vai dentro de BoxDecoration, non tamén en Container.color.

Velaquí un exemplo de Container:

Tamaño, marxe e recheo dun Container
Tamaño, marxe e recheo dun Container

🧪 Combinar os widgets

🔗 DartPad:

Combinar Container, Column, texto e iconas
Combinar Container, Column, texto e iconas

📐 Repartir espazo con Expanded e Flexible

Dentro dunha Row ou Column:

  • Expanded obriga o fillo a ocupar a parte de espazo que lle corresponde.
  • Flexible, co seu axuste habitual FlexFit.loose, permite que o fillo ocupe menos.
  • flex reparte o espazo dispoñible entre estes widgets. Con dous Expanded de flex: 1 e flex: 2, o segundo recibe o dobre de espazo ca o primeiro.

Un uso habitual é deixar que un texto aproveite o ancho restante dunha fila:

const Row(
  children: [
    Icon(Icons.person),
    SizedBox(width: 8),
    Expanded(
      // O texto recibe o ancho restante e pode ocupar varias liñas.
      child: Text('Diego Rodicio, profesor de PMDM no IES San Mamede'),
    ),
  ],
)

Asignar ao texto o ancho restante dunha fila con Expanded
Asignar ao texto o ancho restante dunha fila con Expanded

🧪 Comparar os dous axustes

Os fondos de cor permiten ver o espazo ocupado. Na primeira fila, Toni e Julia enchen o ancho na proporción 1:2. Na segunda, Lucas ocupa só o que necesita e Janeiro enche a parte que lle asigna Expanded; pode quedar espazo libre ao final.

🔗 DartPad:

Reparto do ancho con Expanded e Flexible
Reparto do ancho con Expanded e Flexible

📱 Cando o contido non cabe

O pai marca os límites de tamaño dos fillos. Por iso, width: 200 non garante ese ancho se o espazo dispoñible non o permite.

Row e Column non teñen desprazamento. Se o contido non cabe, pode aparecer unha franxa amarela e negra durante a depuración.

SituaciónSolución habitual
Texto longo dentro dunha RowEnvolver o texto en Expanded ou Flexible.
Poucos elementos que non caben en alturaSingleChildScrollView cunha Column.
Moitos elementos repetidosListView.builder, no seguinte apartado.
Etiquetas que deben pasar á seguinte liñaWrap, na sección «Para saber máis».
const SingleChildScrollView(
  padding: EdgeInsets.all(16),
  child: Column(
    crossAxisAlignment: CrossAxisAlignment.start,
    children: [
      Text('IES San Mamede'),
      SizedBox(height: 16),
      Text('Profesorado: Diego Rodicio, Toni, Janeiro, Julia e Lucas.'),
      // Podemos engadir máis contido; a pantalla permitirá desprazarse.
    ],
  ),
)

⚠️ Non metas un Expanded vertical directamente na Column dun SingleChildScrollView: nesa dirección non hai unha altura máxima que repartir.

Así, neste exemplo vemos o problema e como se resolve con SingleChildScrollView:

Comparación dunha pantalla sen desprazamento e con SingleChildScrollView
Comparación dunha pantalla sen desprazamento e con SingleChildScrollView

📚 Consulta: