Jak vytvořit seznam mřížky ve Flutter pomocí GridView

Při vývoji aplikací ve Flutteru se můžete setkat s potřebou zobrazit seznam položek jako mřížku. Data můžete zobrazit ve formátu mřížky – tj. s řádky a sloupci – pomocí třídy GridView v aplikaci Flutter.

Použití GridView je nejlepší způsob, jak zkombinovat třídy Row a Column a vytvořit rolovací seznam mřížky. Běžným případem použití je zobrazení seznamu fotografií, například v nativních fotografických aplikacích Google a Apple.

V tomto tutoriálu si ukážeme, jak implementovat GridView do vaší aplikace Flutter. Projdeme si také několik praktických příkladů, abyste viděli GridView v akci.

Podrobně se budeme věnovat následujícímu:

  • Co je GridView?
  • Vlastnosti GridView
  • Zobrazení seznamu s pevným počtem položek
  • Zobrazení dlouhého seznamu v GridView
  • Vytvoření responzivního zobrazení GridView

Pokud se učíte vizuálně, podívejte se na tento rychlý videonávod:

Co je GridView?

Ve Flutteru je GridView widget, který zobrazuje seznam položek jako 2D pole. Jednoduše řečeno, položky jsou zobrazeny ve formátu tabulky.

Na rozdíl od běžného seznamu, ve kterém jsou položky vykreslovány pouze v jednom směru, GridView vykresluje položky jak horizontálně, tak vertikálně. Obrázek níže znázorňuje, jak se GridView liší od normálního seznamu v aplikaci Flutter:

Zde je minimální kód pro zprovoznění GridView:

GridView(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
  ),
  children: [
    Image.network('https://picsum.photos/250?image=1'),
    Image.network('https://picsum.photos/250?image=2'),
    Image.network('https://picsum.photos/250?image=3'),
    Image.network('https://picsum.photos/250?image=4'),
  ],
)

gridDelegate je vlastnost, která řídí způsob zobrazení položek v seznamu. V našem příkladu má hodnotu SliverGridDelegateWithFixedCrossAxisCount() s crossAxisCount nastavte na 3 . To znamená, že chceme zobrazit tři položky vodorovně, pokud je směr posouvání svislý, a tři položky svisle, pokud je směr posouvání vodorovný. Výchozí směr posouvání pro jakýkoli seznam je pouze svislý, takže položky jsou zobrazeny vodorovně.

children odkazuje na zde uvedený seznam položek. Přijímá seznam všech widgetů, takže můžete na obrazovce zobrazit cokoli, co byste chtěli.

Zde je výstup:

Zde je návod, jak je kód přeložen do uživatelského rozhraní:

Vlastnosti GridView

Pojďme se podívat na některé vlastnosti GridView.

Další skvělé články od LogRocket:

  • Nenechte si ujít ani okamžik s The Replay, kurátorským zpravodajem společnosti LogRocket
  • Použijte useEffect React k optimalizaci výkonu vaší aplikace
  • Přepínání mezi více verzemi Node
  • Naučte se animovat aplikaci React pomocí AnimXYZ
  • Prozkoumejte Tauri, nový rámec pro vytváření binárních souborů
  • Porovnejte NestJS vs. Express.js
  • Objevte oblíbené ORM používané v prostředí TypeScript

crossAxisSpacing

Nastavení hodnoty pro tuto vlastnost umožňuje umístit mezeru mezi položky na příčné ose. To znamená, že se prostor zobrazí vodorovně, pokud je směr posouvání svislý.

GridView(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
      crossAxisCount: 3, 
      crossAxisSpacing: 16),
  children: [
    Image.network('https://picsum.photos/250?image=1'),
    Image.network('https://picsum.photos/250?image=2'),
    Image.network('https://picsum.photos/250?image=3'),
)

mainAxisSpacing

Hlavní osa odkazuje na osu, ve které se seznam posouvá. Mezera mezi položkami ve směru rolování je dána pomocí mainAxisSpacing vlastnost.

GridView(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
      crossAxisCount: 3, 
      mainAxisSpacing: 16),
  children: [
    Image.network('https://picsum.photos/250?image=1'),
    Image.network('https://picsum.photos/250?image=2'),
    Image.network('https://picsum.photos/250?image=3'),
)

scrollDirection

Možná budete chtít změnit směr posouvání, když je GridView zobrazen v režimu na šířku. Nastavení scrollDirection na Axis.horizontal udělá právě to.

GridView(
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
  ),
  scrollDirection: Axis.horizontal,
  children: [
    ...
  ],
)

physics

Tato vlastnost umožňuje nastavit chování posouvání seznamu. Možná nebudete chtít, aby se seznam posouval vůbec. Řekněme, že zobrazujete například obrázkovou koláž. Posouvání můžete zakázat nastavením physics hodnotu na NeverScrollableScrollPhysics() . Ve výchozím nastavení používá ClampingScrollPhysics() pro Android a BouncingScrollPhysics() pro iOS a vypadá takto:

shrinkWrap

Nastavení shrinkWrap hodnotu na true způsobí, že GridView zabere pouze požadované místo k vyplnění položek ve směru posouvání. Výchozí hodnota je false a rezervuje celou obrazovku, i když položky nejsou v seznamu:

/////shrinkWrap: false,
Column(
  children: [
    Expanded(
      child: GridView(
        gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
          crossAxisCount: 3,
        ),
        shrinkWrap: false,
        children: [... ],
      ),
    ),
    ElevatedButton(onPressed: () {}, child: Text('Close'))
  ],
)
/////shrinkWrap: true,
Column(
  children: [
    GridView(
      gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
        crossAxisCount: 3,
      ),
      shrinkWrap: true,
      children: [...],
    ),
    ElevatedButton(onPressed: () {}, child: Text('Close'))
  ],
)

Když shrinkWrap je false , potřebujeme zabalit GridView do Expanded widgetu tak, aby zabral veškerý dostupný prostor. V opačném případě vyvolá chybu.

Zobrazení seznamu s pevným počtem položek

Flutter má konstruktor pro zobrazení pouze několika položek v GridView s názvem GridView.count() . Tento konstruktor umožňuje vytvořit GridView s pevným počtem položek. Také to zjednodušuje metodu zadávání počtu položek na křížové ose.

Ukázkový kód vypadá takto:

GridView.count(
  crossAxisCount: 3,
  children: [
    ...
  ],
)

Počet položek, které se mají zobrazit v křížové ose, je přiřazen k crossAxisCount vlastnictví. Když se podíváte pozorně, všimnete si, že nepotřebujeme SliverGridDelegateWith FixedCrossAxisCount() už.

GridView.count() lze použít k vytvoření uživatelského rozhraní klávesnice, jako je toto:

Zde je kód pro výše uvedený návrh:

GridView.count(
  crossAxisCount: 3,
  shrinkWrap: true,
  padding: EdgeInsets.only(left: 24, right: 24),
  children: [
    DialKey(
      number: '1',
      letters: '',
    ),
...
  ],
)

shrinkWrap vlastnost je nastavena na true , což způsobí, že GridView uvolní místo na obrazovce.

DialKey() je vlastní widget pro zobrazení jediné klávesy. Vypadá to takto:

// DialKey widget
class DialKey extends StatelessWidget {
  final String number;
  final String letters;

  DialKey({this.number, this.letters});

  @override
  Widget build(BuildContext context) {
    return Center(
      child: Container(
        width: 80,
        height: 80,
        child: FloatingActionButton(
          onPressed: () {},
          backgroundColor: Colors.grey.withOpacity(0.5),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Text(
                '$number',
                style: TextStyle(
                    color: Colors.white,
                    fontSize: 24,
                    fontWeight: FontWeight.bold),
              ),
              Text(
                '$letters',
                style: TextStyle(
                    color: Colors.white,
                    fontSize: 16,
                    fontWeight: FontWeight.bold),
              )
            ],
          ),
        ),
      ),
    );
  }
}

Zobrazení dlouhého seznamu v GridView

Chcete-li zobrazit dlouhý seznam nebo nekonečný počet položek, které mohou pocházet z databáze, potřebujete GridView.builder() konstruktor.

Zde je ukázkový kód:

GridView.builder(
  itemCount: 100,
  itemBuilder: (context, index) => ItemTile(index),
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2,
  ),
)

itemCount představuje počet položek. To pomáhá GridView odhadnout maximální rozsah posouvání.

itemBuilder vytvoří daný widget na základě aktuálního indexu.

Zkusme vytvořit záznam produktu takto:

Kód je následující:

GridView.builder(
  itemCount: 100,
  itemBuilder: (context, index) => ItemTile(index),
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2,
    childAspectRatio: 2,
  ),
)
class ItemTile extends StatelessWidget {
  final int itemNo;

  const ItemTile(
    this.itemNo,
  );

  @override
  Widget build(BuildContext context) {
    final Color color = Colors.primaries[itemNo % Colors.primaries.length];
    return Padding(
      padding: const EdgeInsets.all(8.0),
      child: ListTile(
        tileColor: color.withOpacity(0.3),
        onTap: () {},
        leading: Container(
          width: 50,
          height: 30,
          color: color.withOpacity(0.5),
          child: Placeholder(
            color: color,
          ),
        ),
        title: Text(
          'Product $itemNo',
          key: Key('text_$itemNo'),
        ),
      ),
    );
  }
}

Jedna důležitá věc, kterou je třeba ve výše uvedeném kódu poznamenat, je childAspectRatio vlastnictví. To lze použít k nastavení výšky položek, jak je znázorněno níže:

Vytvoření responzivního zobrazení GridView

S vydáním Flutter 2.0 nyní můžete kromě mobilních aplikací vyvíjet aplikace pro web a desktop. Při vytváření aplikací pro různé platformy se chcete ujistit, že uspokojíte uživatele webu tím, že vytvoříte nejlepší možnou uživatelskou zkušenost. V tomto případě zobrazení více položek na mřížce, když je zobrazena na větší obrazovce, může znamenat dlouhou cestu ke zlepšení uživatelského rozhraní pro uživatele webu.

Upravme předchozí kód tak, aby zobrazoval více položek na křížové ose při zobrazení na větší obrazovce:

//Before
GridView.builder(
  itemCount: 100,
  itemBuilder: (context, index) => ItemTile(index),
  gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2,
    childAspectRatio: 2,
  ),
)
//After
LayoutBuilder(builder: (context, constraints) {
  return GridView.builder(
    itemCount: 100,
    itemBuilder: (context, index) => ItemTile(index),
    gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
      crossAxisCount: constraints.maxWidth > 700 ? 4 : 1,
      childAspectRatio: 5,
    ),
  );
})

Zabalte GridView do LayoutBuilder . LayoutBuilder poskytuje constraints , pomocí kterého lze určit šířku a výšku. Pomocí omezení můžeme vytvořit různá uživatelská rozhraní.

V našem příkladu, kdykoli se rozlišení obrazovky změní na šířku 700 nebo větší, zobrazíme na křížové ose čtyři položky.

Zde je výstup:

Závěr

Pokud jste se dostali až sem, měli byste mít všechny potřebné dovednosti a základní znalosti k vytváření komplexních a poutavých seznamů mřížek ve Flutteru pomocí GridView.

Úplný kód použitý v tomto příkladu je k dispozici na GitHubu.