Diferencia entre revisiones de «Flutter StatefulWidget. Usos»
Ir a la navegación
Ir a la búsqueda
| Línea 67: | Línea 67: | ||
} | } | ||
| − | <syntaxhighlight> | + | </syntaxhighlight> |
| Línea 87: | Línea 87: | ||
}); | }); | ||
} | } | ||
| − | <syntaxhighlight> | + | </syntaxhighlight> |
| Línea 104: | Línea 104: | ||
} | } | ||
............. | ............. | ||
| − | <syntaxhighlight> | + | </syntaxhighlight> |
| Línea 146: | Línea 146: | ||
................... | ................... | ||
| − | <syntaxhighlight> | + | </syntaxhighlight> |
| Línea 232: | Línea 232: | ||
} | } | ||
| − | <syntaxhighlight> | + | </syntaxhighlight> |
| Línea 238: | Línea 238: | ||
<br /> | <br /> | ||
| + | |||
==Paso de datos entre Widgets== | ==Paso de datos entre Widgets== | ||
:* https://medium.com/flutter-community/simple-ways-to-pass-to-and-share-data-with-widgets-pages-f8988534bd5b | :* https://medium.com/flutter-community/simple-ways-to-pass-to-and-share-data-with-widgets-pages-f8988534bd5b | ||
:* https://stackoverflow.com/questions/49491860/flutter-how-to-correctly-use-an-inherited-widget/49492495#49492495 | :* https://stackoverflow.com/questions/49491860/flutter-how-to-correctly-use-an-inherited-widget/49492495#49492495 | ||
Revisión del 16:50 23 sep 2021
Scroll infinito aplicado a ListView
- En este punto vamos a aprender como podemos cargar de forma dinámica un número indeterminado de elementos que se van a visualizar en una lista.
- Para ello partimos del ejemplo realizado en la UD3 - Componentes => ListView.separated.
- En dicho ejemplo disponíamos de un StatelessWidget que visualizaba con un ListView.separated, un conjunto de datos en una lista.
- Lo que voy a hacer en este ejemplo es hacer crecer la lista de forma dinámica, añadiendo nuevos elementos a la misma, al llegar al final de los elementos cargados actualmente.
- Para ello voy a hacer alguna modificación al código.
- Convertiré el StatelessWidget en un StatefulWidget, ya que al añadir nuevos elementos a la lista, voy a necesitar redibujar el Widget.
- Creamos una nueva página en la carpeta pages/stateful de nombre listasinfinite_page.dart
- En todas las páginas haremos lo mismo:
- Importamos la librería de 'material' (recordar que existe un snippet que lo hace automático).
- Creamos una clase (ListasInfinitePage) que derive de StatefulWidget. Se creará (si lo hacéis con un Snippet) una clase asociada que deriva de State.
- Modificamos la clase State y en su métod build hacemos que devuelva un Scaffold con una Appbar (hacerlo con un Snippet)
- Por lo tanto partimos del siguiente código (el atributo _datos no tiene ningún dato, ya que los iremos cargando dinámicamente):
import 'package:flutter/material.dart'; class ListasInfinitePage extends StatefulWidget { const ListasInfinitePage({Key? key}) : super(key: key); @override _ListasInfinitePageState createState() => _ListasInfinitePageState(); } class _ListasInfinitePageState extends State<ListasInfinitePage> { final _datos = <String>[]; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ejemplo de listas con ListView.separated'), ), body: _obtenerLista() ); } Widget _obtenerLista(){ return ListView.separated( itemBuilder: (buildContext, index) => _elementoLista(index), separatorBuilder: (buildContext, index) => Divider(thickness: 10,color: Colors.green,), itemCount: _datos.length); } Widget _elementoLista(pos) { var elemLista = _datos.elementAt(pos); return ListTile( title: Text(elemLista), subtitle: Text('Texto aclaratorio de $elemLista'), leading: Icon(Icons.accessibility), trailing: Icon(Icons.more_vert), onTap: () {}, ); } }
- Primero voy a crear un método que permita añadir un número de elementos determinado a la lista. Lógicamente, al añadirse, se tendrá que llamar al método setState para que redibuje el StatefulWidget:
/** * Añade el número de elementos indicados a la lista */ void _addElementosLista(int num_elementos){ int ultimoElemento = _datos.length; for(int cont=ultimoElemento; cont < ultimoElemento+ num_elementos; cont++){ _datos.add('Elem $cont'); } setState(() { }); }
- Al iniciarse el StatefulWidget, voy a sobreescribir el método initState() para que cargue datos la lista.
- Recordar que ya comenté en la sección de Eventos algo acerca de ciclo de vida de los Widget´s
class _ListasInfinitePageState extends State<ListasInfinitePage> { final _datos = <String>[]; final _numElementosListaAdd = 10; @override void initState() { // TODO: implement initState super.initState(); _addElementosLista(_numElementosListaAdd); } .............
- Ahora lo que tengo que hacer es 'controlar' cuando llego al final de la lista, para que en ese caso, cargar otro conjunto de elementos llamando al método.
- Para ello hacemos uso del ScrollController.
- Los pasos son parecidos a los que ya hicimos con con el TextField, empleando el TextEditingController.
- Creamos un objeto de la clase ScrollController.
- Asociamos el controlador a la lista, con la propiedad del constructor controller.
- En el método initState, 'nos subscribimos' a los cambios de scroll que haya en la lista.
class _ListasInfinitePageState extends State<ListasInfinitePage> { final _datos = <String>[]; final _numElementosListaAdd = 10; ScrollController _scrollController = ScrollController(); @override void initState() { // TODO: implement initState super.initState(); _addElementosLista(_numElementosListaAdd); _scrollController.addListener(() { print('SCROLL'); }); } ................. Widget _obtenerLista(){ return ListView.separated( controller: _scrollController, itemBuilder: (buildContext, index) => _elementoLista(index), separatorBuilder: (buildContext, index) => Divider(thickness: 10,color: Colors.green,), itemCount: _datos.length); } ...................
- Ahora podemos acceder a los métodos de la clase ScrollPosition accediendo con scrollController.position.
- En esa clase están definidas muchas propiedades. Una de ellas es pixels que nos devuelve la posición actual en pixeles, y maxScrollExtent que nos devuelve la posición máxima en pixeles. Por tanto, cuando ambos valores sean iguales significa que hemos llegado al final del scroll de la lista y podremos añadir un nuevo grupo de elementos.
Código completo listasinfinite_page.dart:
import 'package:flutter/material.dart'; class ListasInfinitePage extends StatefulWidget { const ListasInfinitePage({Key? key}) : super(key: key); @override _ListasInfinitePageState createState() => _ListasInfinitePageState(); } class _ListasInfinitePageState extends State<ListasInfinitePage> { final _datos = <String>[]; final _numElementosListaAdd = 10; ScrollController _scrollController = ScrollController(); @override void initState() { // TODO: implement initState super.initState(); _addElementosLista(_numElementosListaAdd); _scrollController.addListener(() { if (_scrollController.position.pixels == _scrollController.position.maxScrollExtent) { _addElementosLista(_numElementosListaAdd); } }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text('Ejemplo de listas con ListView.separated'), ), body: _obtenerLista() ); } Widget _obtenerLista(){ return ListView.separated( controller: _scrollController, itemBuilder: (buildContext, index) => _elementoLista(index), separatorBuilder: (buildContext, index) => Divider(thickness: 10,color: Colors.green,), itemCount: _datos.length); } Widget _elementoLista(pos) { var elemLista = _datos.elementAt(pos); return ListTile( title: Text(elemLista), subtitle: Text('Texto aclaratorio de $elemLista'), leading: Icon(Icons.accessibility), trailing: Icon(Icons.more_vert), onTap: () {}, ); } /** * Añade el número de elementos indicados a la lista */ void _addElementosLista(int num_elementos){ int ultimoElemento = _datos.length; for(int cont=ultimoElemento; cont < ultimoElemento+ num_elementos; cont++){ _datos.add('Elem $cont'); } setState(() { }); } }