Ir al contenido

Referencia

an-scroll-view

Un contenedor con scroll, con tirar-para-recargar y desplazamiento — y los dos estilos que necesita de su padre o no hará scroll en absoluto.

La vista con scroll del sistema: UIScrollView, el ScrollView de Android, NSScrollView. La inercia, el rebote en los bordes, el comportamiento de la barra y cómo interactúa con el teclado son de la plataforma, no una imitación.

El núcleo reporta contentSize —cuánto ocupan los hijos— y lo recorta al marco de la propia vista en el eje por el que no hace scroll: un eje, nunca dos. Cuál sea es cosa de [horizontal].

iOS · iPadOS Android macOS tvOS visionOS watchOS Wear OS
✓ ✓ ✓ ✓ ✓ ✓ ✓
iOS · iPadOS Android macOS watchOS
UIScrollView ScrollView NSScrollView ScrollView
Prop Tipo Por defecto
horizontal boolean | null false Hace scroll de lado en vez de hacia abajo, y coloca los hijos a lo largo de x salvo que la plantilla escriba [style.flexDirection].
showsScrollIndicator boolean | null null
scrollEnabled boolean | null true Whether the finger moves the content.
bounces boolean | null null iOS’s bounce on reaching the end.
refreshing boolean | null false Whether it is refreshing. Setting it to false closes the spinner; the gesture itself opens it, not this prop.
Evento Carga
(refresh) — Pull to refresh.
(scroll) { x, y } Emitted on every frame of the scroll. Layout computes the contentSize by itself: it is the size the children take up, and the core sends it to the UIScrollView whenever it changes.

[ios] — lo que tiene UIKit y los demás no

Sección titulada «[ios] — lo que tiene UIKit y los demás no»
Clave Tipo
pagingEnabled boolean Scrolling comes to rest at multiples of the view’s size. UIScrollView.isPagingEnabled. Android does not ship it: its answer is ViewPager2, which is another view with its own adapter, not a prop.
keyboardDismissMode `‘none’ ‘onDrag’

Hay que dejarle ser más pequeño que su contenido

Sección titulada «Hay que dejarle ser más pequeño que su contenido»

Una vista con scroll medida a la altura de su contenido no es una vista con scroll: es una columna muy alta, y quien hace scroll es la página. Necesita una parte del espacio y permiso para encoger:

<an-view [style.flexGrow]="'1'">
<an-scroll-view [style.flexGrow]="'1'" [style.minHeight]="'0'" [style.overflow]="'scroll'">
…
</an-scroll-view>
</an-view>

Esta es, de largo, la razón más común de que una vista con scroll «no haga nada».

Un [style.height] hace el mismo trabajo y se respeta: el flex-basis con el que el núcleo evita que el contenido dimensione la vista cede ante el tamaño que la plantilla pida en el eje principal del padre.

<an-scroll-view [horizontal]="true" [style.height]="'96'">
@for (card of cards(); track card.id) {
<an-view [style.width]="'120'">…</an-view>
}
</an-scroll-view>

[horizontal] también gira los hijos, porque una vista con scroll horizontal cuyos hijos siguen apilándose hacia abajo nunca es más ancha que ella misma y por tanto no tiene nada por lo que desplazarse. Eso es un valor por defecto: escribir [style.flexDirection] recupera la decisión.

Es un booleano y no un enum direction porque un enum tendría que ofrecer both, y both no es algo que Android pueda ser: ScrollView y HorizontalScrollView son dos clases, y una vista no cambia de clase una vez creada.

<an-scroll-view
[style.flexGrow]="'1'"
[style.overflow]="'scroll'"
[refreshing]="loading()"
(refresh)="reload()"
(scroll)="offset.set($event.y)">
@for (row of rows(); track row.id) {
<an-text>{{ row.name }}</an-text>
}
</an-scroll-view>

Todas las primitivas llevan además las props de la base —fondo, borde, opacidad, las transformaciones, animate, el contrato de accesibilidad— y todos los gestos. La base completa está en Componentes, y las cargas en Eventos.