Dando continuidade à série Flutter de criação de listas com Listview, hoje usaremos como exemplo o construtor ListView.builder para exibir uma grande quantidade de itens na lista de itens.
Caso tenha perdido os artigos anteriores, confira:
Para exibir uma lista de itens com uma grande quantidade de itens, podemos usar o construtor ListView.builder.
A principal diferença entre ListView e ListView.builder é que o construtor ListView padrão requer que criemos todos os itens de uma só vez, enquanto o construtor ListView.builder criará itens à medida em que eles forem rolados para a tela, como por demanda.
Criando um novo projeto Flutter
No VS Code abra a paleta de comandos (Ctrl + Shift + P) e digite flutter.
A seguir, clique em New Project, informe o nome listviewbuilder e escolha a pasta onde o projeto será criado.
Como vamos exibir uma imagem local (planeta1.jpg) em nossa aplicação, precisamos criar uma pasta assets na raiz do projeto e copiar a imagem que vamos exibir para essa pasta (você pode usar qualquer nome de pasta).
Para poder exibir a imagem em nossa aplicação Flutter, precisamos adicionar o nome dessa imagem dentro do arquivo pubspec.yaml.
Adicione a seguinte linha de código dentro do arquivo pubspec.yaml.
Ao final, nosso projeto terá a seguinte estrutura:
Criando o Stateful Widgets
No Flutter, tudo são Widgets, e podemos ter dois tipos de widgets: Stateless e Statefull, ou seja, sem estado e com estado.
Neste exemplo vamos criar um Stateful Widget, ou seja, um widget dinâmico que vai poder ser alterado por uma ação do usuário.
Substitua o código do arquivo main.dart pelo código abaixo:
import 'package:flutter/material.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
List<String> _planetas = ['Saturno'];
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: Colors.deepPurple),
home: Scaffold(
appBar: AppBar(title: Text('Lista de Planetasa')),
body: Column(children: [
Container(
margin: EdgeInsets.all(10.0),
child: RaisedButton(
color: Theme.of(context).primaryColor,
splashColor: Colors.blueGrey,
textColor: Colors.white,
onPressed: () {
setState(() {
_planetas.add('Saturno');
});
},
child: Text('Adicionar Planetas'))),
Column(
children: _planetas
.map((element) => Card(
child: Column(
children: <Widget>[
Image.asset('assets/planeta1.jpg'),
Text(element,
style: TextStyle(color: Colors.deepPurple))
],
),
))
.toList()),
]),
),
);
}
}
Neste código criamos um widget com estado e, em seguida, configuramos o tema para o aplicativo Flutter. Em seguida, pegamos um botão criado e, quando o usuário pressiona o botão, adicionamos a imagem ao array e exibimos a imagem com o widget de Card.
Dessa forma, estamos exibindo dois itens: Image e Text.
Para executar, podemos pressionar F5, ou, no terminal de comandos, estando posicionado na pasta do projeto, basta digitar flutter run -d all.
Executando o projeto iremos obter o resultado abaixo:
Ao clicar no botão para Adicionar Planetas, veremos uma mensagem alertando que houve um overflow indicando que a imagem incluída passou os limites de exibição.
Resolvendo o problema
Para resolver este problema, temos que criar uma lista rolável usando o widget ListView.builder.
O construtor ListView.builder() é apropriado para exibições de lista com um número grande (ou infinito) de filhos, porque o construtor é chamado apenas para aqueles filhos visíveis.
Vamos fornecer um itemCount não nulo para melhorar a capacidade do ListView de estimar a extensão máxima de rolagem.
O retorno de chamada itemBuilder será chamado apenas com índices maiores ou iguais a zero e menores que itemCount.
Para fazer essa implementação vamos dividir o nosso projeto em dois arquivos:
- planetas.dart
- main.dart
O arquivo planetas.dart será responsável apenas por exibir os itens no widget Card com a ajuda do widget de construtor ListView.builder.
Inclua um novo arquivo chamado planetas.dart na pasta lib e a seguir inclua o código abaixo:
import 'package:flutter/material.dart';
class Planetas extends StatelessWidget {
final List<String> planetas;
Planetas(this.planetas);
Widget _buildPlanetaItem(BuildContext context, int index) {
return Card(
child: Column(
children: <Widget>[
Image.asset('assets/planeta1.jpg'),
Text(planetas[index], style: TextStyle(color: Colors.deepPurple))
],
),
);
}
@override
Widget build(BuildContext context) {
return ListView.builder(
itemBuilder: _buildPlanetaItem,
itemCount: planetas.length,
);
}
}
Esse código representa a classe Planetas, que possui um método chamado _buildPlanetaItem, que retorna o widget ListView.builder.
O widget ListView.builder usa dois argumentos:
- Uma função que retorna o Widget
- Um itemCount, que é o comprimento de uma matriz de planetas
A seguir vamos alterar o código do arquivo main.dart conforme abaixo:
import 'package:flutter/material.dart';
import './planetas.dart';
void main() => runApp(MyApp());
class MyApp extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _MyAppState();
}
}
class _MyAppState extends State<MyApp> {
List<String> _planetas = [];
@override
void initState() {
super.initState();
_planetas.add('Saturno');
}
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: Colors.deepPurple),
home: Scaffold(
appBar: AppBar(title: Text('Lista de Planetas')),
body: Column(children: [
Container(
margin: EdgeInsets.all(10.0),
child: RaisedButton(
color: Theme.of(context).primaryColor,
splashColor: Colors.blueGrey,
textColor: Colors.white,
onPressed: () {
setState(() {
_planetas.add('Saturno');
});
},
child: Text('Saturno'))),
Expanded(child: Planetas(_planetas))
])));
}
}
Aqui usamos o widget Expanded, que permite expandir um filho de uma Linha, Coluna ou Flex.
O uso de um widget Expanded faz com que o filho de uma Linha, Coluna ou Flex se expanda para preencher o espaço disponível no eixo primário (por exemplo, horizontalmente para uma linha ou verticalmente para uma coluna). Se vários filhos são expandidos, um espaço disponível é dividido entre eles de acordo com o fator flex.
Aqui, passamos o construtor de planetas importado com o argumento da matriz _planetas.
Agora, executando novamente ou apenas dando o hot reload, incluindo mais dois itens na lista veremos o seguinte resultado:
Temos agora que a lista vai exibindo os itens conforme vão sendo incluídos.
Esta é a maneira mais eficiente de exibir uma lista longa com o ListView, usando o construtor ListView.builder().
Na próxima parte do artigo veremos como obter dados de uma API REST no formato JSON via HTTP e exibir em um ListView.