PrimaryScrollController predeterminado en Desktop
The `PrimaryScrollController` will no longer attach to vertical `ScrollView`s automatically on Desktop.
Resumen
#La API de PrimaryScrollController se ha actualizado para que ya no se asocie automáticamente
a los ScrollViews verticales en plataformas de escritorio (desktop).
Contexto
#Antes de este cambio, ScrollView.primary tenía como valor predeterminado true si un
ScrollView tenía una dirección de desplazamiento Axis.vertical y no se
había proporcionado ya un ScrollController. Esto permitía que patrones de UI comunes, como la
función de deslizar hacia arriba en iOS, funcionaran de inmediato para las aplicaciones de Flutter.
Sin embargo, en escritorio, este valor predeterminado a menudo causaba el siguiente error de aserción:
ScrollController attached to multiple ScrollViews.
Aunque es común que una aplicación móvil muestre un ScrollView a la vez,
los patrones de UI de escritorio son más propensos a mostrar múltiples ScrollViews
uno al lado del otro. La implementación anterior de PrimaryScrollController entraba en conflicto
con este patrón, lo que resultaba en un mensaje de error que a menudo no era útil. Para solucionar esto,
PrimaryScrollController se ha actualizado con parámetros adicionales, así
como mejores mensajes de error en múltiples widgets que dependen de él.
Descripción del cambio
#La implementación anterior de ScrollView hacía que primary fuera true por
defecto para todos los ScrollViews verticales que no tuvieran ya un
ScrollController, en todas las plataformas. Este comportamiento predeterminado no siempre era claro,
particularmente porque es independiente del propio PrimaryScrollController.
// Previously, this ListView would always result in primary being true,
// and attached to the PrimaryScrollController on all platforms.
Scaffold(
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
}
),
);
La implementación cambia ScrollView.primary para que admita valores nulos (nullable), reubicando la toma de decisiones
de respaldo en PrimaryScrollController.
Cuando primary es null y no se ha proporcionado ningún ScrollController, el
ScrollView
buscará el PrimaryScrollController y en su lugar llamará a shouldInherit
para
determinar si el ScrollView dado debe usar el PrimaryScrollController.
Los nuevos miembros de la clase PrimaryScrollController,
automaticallyInheritForPlatforms y scrollDirection, se evalúan en
shouldInherit, lo que brinda a los usuarios claridad y control sobre el
comportamiento de PrimaryScrollController.
Por defecto, se mantiene la compatibilidad con versiones anteriores para plataformas móviles.
PrimaryScrollController.shouldInherit devuelve true para ScrollViews
verticales. En escritorio, este devuelve false de forma predeterminada.
// Only on mobile platforms will this attach to the PrimaryScrollController by
// default.
Scaffold(
body: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Text('Item $index');
}
),
);
Para cambiar el comportamiento predeterminado, los usuarios pueden establecer ScrollView.primary en true o false para
gestionar explícitamente el PrimaryScrollController para un ScrollView individual.
Para el comportamiento en múltiples ScrollViews, el PrimaryScrollController
ahora es
configurable configurando la plataforma específica, así como la dirección de desplazamiento
que se prefiere para la herencia.
Los Widgets que usan el PrimaryScrollController, como NestedScrollView,
Scrollbar y DropdownMenuButton no experimentarán ningún cambio en su funcionalidad
existente. Características como el scroll-to-top de iOS también continuarán funcionando como
se espera sin ninguna migración.
Las clases ScrollAction y ScrollIntent en escritorio son las únicas afectadas por
este cambio y requieren migración. De forma predeterminada, PrimaryScrollController
se
utiliza para ejecutar el desplazamiento de teclado de respaldo (Shortcuts) si el
Focus actual está
contenido dentro de un Scrollable. Dado que mostrar más de un ScrollView
uno al lado del otro es común en plataformas de escritorio, no es posible para
Flutter decidir "¿Qué ScrollView debería ser el primario en esta vista y recibir
la acción de desplazamiento del teclado?"
Si había más de un ScrollView presente antes de este cambio, se lanzaba la misma
aserción (ScrollController attached to multiple ScrollViews.).
Ahora, en plataformas de escritorio, los usuarios deben especificar primary: true para
designar qué ScrollView es el respaldo para recibir Shortcuts de teclado
no controlados.
Guía de migración
#Código antes de la migración:
// These side-by-side ListViews would throw errors from Scrollbars and
// ScrollActions previously due to the PrimaryScrollController.
Scaffold(
body: LayoutBuilder(
builder: (context, constraints) {
return Row(
children: [
SizedBox(
height: constraints.maxHeight,
width: constraints.maxWidth / 2,
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Text('List 1 - Item $index');
}
),
),
SizedBox(
height: constraints.maxHeight,
width: constraints.maxWidth / 2,
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Text('List 2 - Item $index');
}
),
),
]
);
},
),
);
Código después de la migración:
// These side-by-side ListViews will no longer throw errors, but for
// default ScrollActions, one will need to be designated as primary.
Scaffold(
body: LayoutBuilder(
builder: (context, constraints) {
return Row(
children: [
SizedBox(
height: constraints.maxHeight,
width: constraints.maxWidth / 2,
child: ListView.builder(
// This ScrollView will use the PrimaryScrollController
primary: true,
itemBuilder: (BuildContext context, int index) {
return Text('List 1 - Item $index');
}
),
),
SizedBox(
height: constraints.maxHeight,
width: constraints.maxWidth / 2,
child: ListView.builder(
itemBuilder: (BuildContext context, int index) {
return Text('List 2 - Item $index');
}
),
),
]
);
},
),
);
Timeline
#Llegó en la versión: 3.3.0-0.0.pre
En lanzamiento estable: 3.3
Referencias
#Documentación de la API:
Documento de diseño:
Issues relevantes:
PRs relevantes:
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-05-05. Ver código fuente oreportar un problema.