El desplazamiento mediante la típica barra de desplazamiento es fundamental en cualquier app y aunque Flutter hace que muchas cosas sean simples, el Scrollbar widget puede ser complicado o difícil de usar si no se entiende bien.
Uno de los elementos fundamentales al momento de desarrollar cualquier tipo de aplicaciones y sobre todo las móviles por cuestiones del espacio disponible, es el scroll o la barra de desplazamiento.
Para agregar una barra de desplazamiento a un ScrollView, ajuste el widget de vista de desplazamiento en un widget de barra de desplazamiento. Usando este widget podemos desplazarnos por un widget.
La barra de desplazamiento permite al usuario saltar o desplazarse hacia una parte de la interfaz cuando esta no se puede visualizar completamente en la pantalla por vez.
Aquí te cuento todo lo que necesitas para dominarlo (incluyendo un par de aprendizajes reales que me llevé mientras creaba listados de cursos y libros en mi propia app).
Flutter proporciona una inmensa cantidad de widgets que nos ayuda en la creación de aplicaciones de manera modular, como si de piezas de lego se tratase, La idea central es que cree su interfaz de usuario a partir de widgets. Los widgets describen cómo debe ser la vista o pantalla de tu aplicación según la organización y propiedades del mismo.
Recuerda que el widget que vimos antes nos permitía conocer como detectar desplazamientos mediante gestos con el efecto Swipe en Flutter.
Qué es el Scrollbar en Flutter y para qué sirve
El Scrollbar es un widget que se envuelve alrededor de cualquier componente desplazable (ListView, GridView, SingleChildScrollView…) y muestra una barra visual que indica la posición dentro del contenido.
En apps con mucho contenido —como me ocurrió en mi app de academia— los usuarios pueden perderse entre tantos elementos. La barra les da una referencia visual inmediata.
Cuándo usarlo en una app real
- Listas largas (cursos, productos, noticias).
- Contenido educativo o catálogos (como mi lista de libros).
- App donde la navegación vertical debe ser clara.
- Cualquier vista donde los usuarios deban ver “dónde están”.
Atributos principales del Scrollbar (explicados con ejemplos)
El Scrollbar tiene varios atributos que definen su comportamiento y apariencia.
- controller e isAlwaysShown
- controller: permite controlar manualmente la posición.
En mi caso fue esencial: el Scrollbar no aparecía hasta que usé un ScrollController. - isAlwaysShown: obliga al Scrollbar a mantenerse visible.
- controller: permite controlar manualmente la posición.
- thickness, hoverThickness y radius
- thickness: ancho del thumb (la barrita).
- hoverThickness: grosor al pasar el cursor (muy útil en web o desktop).
Aquí descubrí algo clave: al ajustar hoverThickness la barra empezó a ser mucho más intuitiva para mis usuarios. - radius: redondea los bordes del thumb.
- showTrackOnHover e interactive
- showTrackOnHover: muestra la pista del scroll al hacer hover.
- interactive: permite arrastrar la barra.
- Personalización visual del thumb y del track
Desde Flutter 3+ puedes personalizar incluso colores, decoraciones y animaciones mediante ScrollbarTheme.
Cómo implementar Scrollbar con ListView, GridView y SingleChildScrollView
Ejemplo básico paso a paso
Scrollbar(
child: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) => Text('Item $index'),
),
);Ejemplo con ScrollController (para cuando el Scrollbar no aparece)
Este es el patrón más recomendable:
final controller = ScrollController();
Scrollbar(
controller: controller,
child: ListView.builder(
controller: controller,
itemCount: 30,
itemBuilder: (_, i) => ListTile(title: Text('Curso $i')),
),
);En este fragmento de código, usamos un widget de tipo Listview y lo envolvimos en la barra de desplazamiento. En esto, isAlwaysShown es un bool que indica que la barra de desplazamiento debe ser visible, incluso cuando un desplazamiento no está en marcha, y showTrackOnHover Controles si la barra se mostrará al momento de hacer el scroll o estará siempre oculta.
Pero recuerda que puedes emplear cualquier tipo de widget que tu sabes no va a caber en la pantalla.
Expanded(
child: Scrollbar(
isAlwaysShown: _isAlwaysShown,
showTrackOnHover: _showTrackOnHover,
child: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) => MyItem(index),
),
),
),Agregaremos el método listview.builder() que nos permitirá hacer o crear de manera demostrativa algunos elementos para que no quepan en la pantalla y aparezca la barra de desplazamiento.
Finalmente, la totalidad del código:
import 'package:flutter/material.dart';
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
bool _isAlwaysShown = true;
bool _showTrackOnHover = false;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Scrollbar Demo'),
),
body: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Expanded(
child: Scrollbar(
isAlwaysShown: _isAlwaysShown,
showTrackOnHover: _showTrackOnHover,
hoverThickness: 30.0,
child: ListView.builder(
itemCount: 20,
itemBuilder: (context, index) => MyItem(index),
),
),
),
Divider(height: 1),
],
),
);
}
}
class MyItem extends StatelessWidget {
final int index;
const MyItem(this.index);
@override
Widget build(BuildContext context) {
final color = Colors.primaries[index % Colors.primaries.length];
final hexRgb = color.shade500.toString().substring(10, 16).toUpperCase();
return ListTile(
contentPadding: EdgeInsets.symmetric(horizontal: 20, vertical: 20),
leading: AspectRatio(
aspectRatio: 1,
child: Container(
color: color,
)),
title: Text('Material Color #${index + 1}'),
subtitle: Text('#$hexRgb'),
);
}
}
Ejemplo avanzado con personalización
El Scrollbar, envuelve un ListView.builder) para proporcionarle la barra de desplazamiento.
Scrollbar(
controller: controller,
thumbVisibility: true,
thickness: 8,
radius: Radius.circular(12),
hoverThickness: 14,
child: ListView.builder(
controller: controller,
itemCount: 50,
itemBuilder: (_, i) => ListTile(title: Text('Libro $i')),
),
);- thumbVisibility: true,
- Hace que la "tira" o "pull" de la barra de desplazamiento sea siempre visible, incluso cuando no se está desplazando. Por defecto, solo aparece al hacer scroll.
- thickness: 8,
- Define el grosor de la barra de desplazamiento (el thumb).
- radius: Radius.circular(12),
- Aplica un radio de borde de 12 píxeles al thumb, con esquinas redondeadas.
- hoverThickness: 14,
- Especifica el grosor que tendrá la barra de desplazamiento cuando el usuario pase el cursor por encima (hover), haciéndola más ancha (14) que su grosor normal (8).
Errores comunes y cómo solucionarlos
El Scrollbar no aparece
Causas típicas:
- No compartiste el mismo ScrollController en el Scrollbar y el ListView.
- El contenido no excede la pantalla (no hay scroll).
- Usaste múltiples scrolls anidados sin control.
Solución:
final controller = ScrollController();
Scrollbar(controller: controller, child: ListView(controller: controller));Problemas al combinar Scrollbar dentro de Column o Expanded
Si el Scrollbar está dentro de un Column, necesitas un Expanded:
Expanded(
child: Scrollbar(
child: ListView(...),
),
);Scrolls anidados
Evita ScrollView dentro de ScrollView. Usa:
- CustomScrollView, o
- PrimaryScrollController.
Preguntas frecuentes sobre Scrollbar en Flutter
- ¿Por qué el Scrollbar no aparece?
- Generalmente porque no usas un ScrollController compartido.
- ¿Cómo hacerlo siempre visible?
- Usa thumbVisibility: true (o isAlwaysShown en versiones antiguas).
- ¿Cómo personalizar el grosor?
- thickness y hoverThickness.
- ¿Funciona con GridView?
- Sí, siempre que le pases el controller a ambos widgets.
Aprende a implementar un pinch-to-zoom en Flutter.
Acepto recibir anuncios de interes sobre este Blog.
Vamos a conocer como aplicar un scroll a nuestros widgets en Flutter, lo cual es un tema fundamental para poder colocar contenido que sea más grande que el tamaño de la pantalla.