Slivers al Descubierto
Ante de iniciar con este post, el cual seria el 2 en el que trabajo como traducción, quiero darle el crédito que se merece a la creadora original de este post Emily Fortuna una gran persona y excelente developer, con la que he tenido oportunidad de intercambiar una par de palabras y de la cual muchos de nosotros hemos aprendido de sus post y videos donde habla de Flutter, ahora a lo que venimos!

O bien, cómo hacer técnicas de scrolling atractivas en tu aplicación móvil con Flutter
Hola, intrépidos fans de Flutter! Hoy vamos a profundizar en un tema altamente especializado — algo que la mayoría de los desarrolladores de aplicaciones pueden ignorar alegremente y crear aplicaciones muy atractivas sin necesidad de saber o entender. Normalmente, si necesita desplazarse por algo, ListView y GridView harán el trabajo. Hecho y hecho. Pero, si buscas un conocimiento más profundo y quieres darle sabor a tus habilidades de scrolling:


Sigamos adelante…
¿Qué es una Sliver y por qué la quiero?
Alrededor de la web veo un gran número de FOS. Eso es (Fear Of Slivers) miedo a las slivers para los que no lo saben. Pero un slivers es sólo una parte de un área que se puede desplazar. ¡Eso es todo! Debajo de las cubiertas, todas las vistas desplazables que utiliza, como ListView y GridView, se implementan realmente utilizando Slivers. Puede pensar en Slivers como una interfaz de nivel inferior, que proporciona un control más preciso sobre la implementación del área de desplazamiento. Debido a que los slivers pueden construir perezosamente cada artículo mientras se desplaza a la vista, los slivers son particularmente útiles para desplazarse de manera eficiente a través de un gran número de children.
Es posible que desee este control adicional en el comportamiento de desplazamiento si usted:
- Desea una barra de aplicaciones con un comportamiento no estándar (desaparecer a medida que se desplaza, cambiar el tamaño o el color a medida que se desplaza, etc.).
- Necesita desplazarse por una lista de elementos y una cuadrícula de elementos todos juntos como una unidad. (Sí, puede hacer esto con una tabla en un ListView pero eso es mucho menos eficiente, particularmente si tiene una tabla grande.
- Hacer algo raro como una lista colapsada con encabezados (ver gif a la derecha en la parte superior de esta página).

¿Cómo lo uso?
Todos estos componentes del sliver van dentro de un CustomScrollView. El resto depende de ti para combinar tu lista de slivers para hacer tu área de desplazamiento personalizada. Puedes reinventar un ListView poniendo un SliverList dentro de un CustomScrollView y no poner nada más.
SliverList
SliverList toma un parámetro de delegado que proporciona los elementos de la lista a medida que se desplazan a la vista. Puede especificar la lista real de children con un SliverChildListDelegate o construirlos perezosamente con un SliverChildBuilderDelegate.
// Lista explícita de niños. No hay ahorros de eficiencia aquí ya
// que los children ya están construidosSliverList(
delegate: SliverChildListDelegate(
[
Container(color: Colors.red, height: 150.0),
Container(color: Colors.purple, height: 150.0),
Container(color: Colors.green, height: 150.0),
],
),
);// Para construir una lista infinita desplazable de diferentes
// contenedores de colorSliverList(
delegate: SliverChildBuilderDelegate((BuildContext context, int index) {
// Para convertir esta lista infinita a una lista con tres
// elementos descomenta la siguiente linea
// if (index > 3) return null;
return Container(color: getRandomColor(), height: 150.0);
},
// o comenta la siguiente linea
// childCount: 3,
),
);
SliverGrid
- Contar constructor para contar cuántos artículos están, en este caso, en el eje horizontal:
SliverGrid.count(children: scrollItems, crossAxisCount: 4) - Constructor de extensión para especificar el ancho máximo de los elementos para determinar cuántos deben caber en una cuadrícula. Esto es muy útil si los elementos de su cuadrícula varían en tamaño, puede limitar el espacio que deben ocupar (en este caso, horizontalmente).
SliverGrid.extent(children: scrollItems, maxCrossAxisExtent: 90.0) // 90 logical pixels - Constructor por defecto, pasando un parámetro gridDelegate explícito:
// Re-implementing the above SliverGrid.count example:
SliverGrid(
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 4,
),
delegate: SliverChildBuilderDelegate(
(BuildContext context, int index) {
return new Container(
color: randomColor(),
height: 150.0);
}
);

SliverAppBar
Okay, okay, suficiente exposición. Esto es lo que sé que todos han estado esperando. ¿Cómo puedo hacer que esas magníficas app-bars de expansión y contracción? El secreto es establecer tanto el parámetro flexibleSpace como el parámetro expandedHeight. Puede configurar ambos para una altura y apariencia diferentes para su app bar cuando se expande a su tamaño completo en comparación con la versión “comprimida”.

Aqui esta el código para este ejemplo:
CustomScrollView(
slivers: <Widget>[
SliverAppBar(
title: Text('SliverAppBar'),
backgroundColor: Colors.green,
expandedHeight: 200.0,
flexibleSpace: FlexibleSpaceBar(
background: Image.asset('assets/forest.jpg', fit: BoxFit.cover),
),
),
SliverFixedExtentList(
itemExtent: 150.0,
delegate: SliverChildListDelegate(
[
Container(color: Colors.red),
Container(color: Colors.purple),
Container(color: Colors.green),
Container(color: Colors.orange),
Container(color: Colors.yellow),
Container(color: Colors.pink),
],
),
),
],
);Hay algunas personalizaciones adicionales que puedes añadir en SliverAppBar. Puede establecer el parámetro flotante como verdadero para que la barra de aplicaciones vuelva a aparecer cuando se desplace hacia abajo, incluso si no ha llegado a la parte superior de la lista.

Si agrega ambos parámetros de ajuste con el parámetro flotante, puede hacer que la app bar vuelva a estar a la vista cuando se desplace hacia abajo.

Poniendo todo junto: una lista de desplazamiento plegable con SliverPersistentHeader
Intenté imaginar el comportamiento de desplazamiento más inusual que se me ocurrió y que todavía podría ser útil. Se me ocurrió esta lista desplegable:

import 'package:flutter/material.dart';import 'dart:math' as math;void main() => runApp(MyApp());class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Collapsing List Demo')),
body: CollapsingList(),
),
);
}
}class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
_SliverAppBarDelegate({
@required this.minHeight,
@required this.maxHeight,
@required this.child,
});final double minHeight;
final double maxHeight;
final Widget child;@override
double get minExtent => minHeight;@override
double get maxExtent => math.max(maxHeight, minHeight);@override
Widget build(
BuildContext context,
double shrinkOffset,
bool overlapsContent)
{
return new SizedBox.expand(child: child);
}@override
bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
return maxHeight != oldDelegate.maxHeight ||
minHeight != oldDelegate.minHeight ||
child != oldDelegate.child;
}
}class CollapsingList extends StatelessWidget {
SliverPersistentHeader makeHeader(String headerText) {
return SliverPersistentHeader(
pinned: true,
delegate: _SliverAppBarDelegate(
minHeight: 60.0,
maxHeight: 200.0,
child: Container(
color: Colors.lightBlue, child: Center(child:
Text(headerText))),
),
);
}@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: <Widget>[
makeHeader('Header Section 1'),
SliverGrid.count(
crossAxisCount: 3,
children: [
Container(color: Colors.red, height: 150.0),
Container(color: Colors.purple, height: 150.0),
Container(color: Colors.green, height: 150.0),
Container(color: Colors.orange, height: 150.0),
Container(color: Colors.yellow, height: 150.0),
Container(color: Colors.pink, height: 150.0),
Container(color: Colors.cyan, height: 150.0),
Container(color: Colors.indigo, height: 150.0),
Container(color: Colors.blue, height: 150.0),
],
),
makeHeader('Header Section 2'),
SliverFixedExtentList(
itemExtent: 150.0,
delegate: SliverChildListDelegate(
[
Container(color: Colors.red),
Container(color: Colors.purple),
Container(color: Colors.green),
Container(color: Colors.orange),
Container(color: Colors.yellow),
],
),
),
makeHeader('Header Section 3'),
SliverGrid(
gridDelegate:
new SliverGridDelegateWithMaxCrossAxisExtent(
maxCrossAxisExtent: 200.0,
mainAxisSpacing: 10.0,
crossAxisSpacing: 10.0,
childAspectRatio: 4.0,
),
delegate: new SliverChildBuilderDelegate(
(BuildContext context, int index) {
return new Container(
alignment: Alignment.center,
color: Colors.teal[100 * (index % 9)],
child: new Text('grid item $index'),
);
},
childCount: 20,
),
),
makeHeader('Header Section 4'),
// Yes, this could also be a SliverFixedExtentList. Writing
// this way just for an example of SliverList construction.
SliverList(
delegate: SliverChildListDelegate(
[
Container(color: Colors.pink, height: 150.0),
Container(color: Colors.cyan, height: 150.0),
Container(color: Colors.indigo, height: 150.0),
Container(color: Colors.blue, height: 150.0),
],
),
),
],
);
}
}
El último paso (ejercicio a la izquierda del lector) sería añadir un GestureDetector para que al tocar una de las cabeceras pueda saltar a esa sección de la lista. Tome su nuevo conocimiento de Slivers y aplíquelo a GestureDetection para hacer una lista de colapso genial!
Aquí les dejo la cuenta directa de Emily Fortuna de Medium, GitHub y Twitter una persona muy recomendada para seguir, siempre compartiendo información importante del Flutterverse!
Por otra parte les dejo mi cuenta de Twitter y Github no tan interesantes como las de Emily pero procuro informar de todo lo que hay nuevo de Flutter en Inglés y Español.
Esto es todo de mi parte, espero estar de regreso próximamente con mucho mas contenido interesante de Flutter.

No dejen de aletear!!!


