SwipeRefresh
Material | Material 3 |
---|---|
![]() | ![]() |
El componente PullRefresh
mejor conocido como SwipeRefresh
es una funcionalidad
que permite a los usuarios actualizar el contenido de la pantalla mediante
un gesto de arrastre hacia abajo. Cuando el usuario desliza hacia abajo en la parte superior de una
lista o una vista de desplazamiento, se activa una animación de “pull-to-refresh” (arrastrar para actualizar)
que indica que la aplicación está recargando los datos. Este gesto es comúnmente utilizado para refrescar el
contenido de feeds de noticias, correos electrónicos, y otras listas de datos actualizables.
Implementación
Definición del componente
@Composable@ExperimentalMaterialApifun PullRefreshIndicator( refreshing: Boolean, state: PullRefreshState, modifier: Modifier = Modifier, backgroundColor: Color = MaterialTheme.colors.surface, contentColor: Color = contentColorFor(backgroundColor), scale: Boolean = false): Unit
Atributo | Descripción |
---|---|
refreshing | Indica cuando el refresh está ocurriendo. |
state | El estado que rastrea cuánto se ha realizado el gesto. |
modifier | Modificador opcional para personalizar el estilo y el diseño del componente. |
backgroundColor | El color del fondo del indicador. |
contentColor | El color del arco y la flecha del indicador. |
scale | Indica si el tamaño del indicador cambia según el progreso del arrastre o no. |
@Composable@ExperimentalMaterial3Apifun PullToRefreshBox( isRefreshing: Boolean, onRefresh: () -> Unit, modifier: Modifier = Modifier, state: PullToRefreshState = rememberPullToRefreshState(), contentAlignment: Alignment = Alignment.TopStart, indicator: @Composable BoxScope.() -> Unit = { Indicator( modifier = Modifier.align(Alignment.TopCenter), isRefreshing = isRefreshing, state = state ) }, content: @Composable BoxScope.() -> Unit): Unit
Atributo | Descripción |
---|---|
isRefreshing | Indica cuando el refresh está ocurriendo. |
onRefresh | Función lambda que se llama cuando el usuario arrastra lo suficiente para solicitar una actualización. |
modifier | Modificador opcional para personalizar el estilo y el diseño del componente. |
state | El estado que rastrea cuánto se ha realizado el gesto. |
indicator | Componente indicador que se muestra encima del contenido cuando el usuario comienza a arrastrar o cuando se está realizando una actualización. |
content | Función lambda que define el contenido principal del elemento. |
Ejemplos

package com.example.swiperefresh
import android.os.Bundleimport androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport androidx.activity.enableEdgeToEdgeimport androidx.compose.foundation.layout.Arrangementimport androidx.compose.foundation.layout.Boximport androidx.compose.foundation.layout.PaddingValuesimport androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.foundation.layout.paddingimport androidx.compose.foundation.lazy.LazyColumnimport androidx.compose.foundation.lazy.LazyListStateimport androidx.compose.foundation.lazy.itemsimport androidx.compose.foundation.lazy.rememberLazyListStateimport androidx.compose.material.ExperimentalMaterialApiimport androidx.compose.material.Scaffoldimport androidx.compose.material.Textimport androidx.compose.material.pullrefresh.PullRefreshIndicatorimport androidx.compose.material.pullrefresh.pullRefreshimport androidx.compose.material.pullrefresh.rememberPullRefreshStateimport androidx.compose.runtime.Composableimport androidx.compose.runtime.getValueimport androidx.compose.runtime.mutableStateOfimport androidx.compose.runtime.rememberimport androidx.compose.runtime.rememberCoroutineScopeimport androidx.compose.runtime.setValueimport androidx.compose.ui.Alignmentimport androidx.compose.ui.Modifierimport androidx.compose.ui.unit.dpimport com.example.swiperefresh.ui.theme.SwipeRefreshThemeimport kotlinx.coroutines.delayimport kotlinx.coroutines.launch
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { SwipeRefreshTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> val items = remember { (1..100).map { "Item $it" } } var isRefreshing by remember { mutableStateOf(false) } val scope = rememberCoroutineScope()
Box( modifier = Modifier .fillMaxSize() .padding(innerPadding) .padding(top = 24.dp) ) { PullToRefreshLazyColumn( items = items, content = { Text(text = it) }, isRefreshing = isRefreshing, onRefresh = { scope.launch { isRefreshing = true delay(2000) isRefreshing = false } } ) } } } } }}
@OptIn(ExperimentalMaterialApi::class)@Composablefun <T> PullToRefreshLazyColumn( items: List<T>, content: @Composable (T) -> Unit, isRefreshing: Boolean, onRefresh: () -> Unit, modifier: Modifier = Modifier, lazyListState: LazyListState = rememberLazyListState()) { val pullToRefreshState = rememberPullRefreshState(isRefreshing, onRefresh = onRefresh)
Box( modifier = modifier .fillMaxSize() ) { LazyColumn( state = lazyListState, contentPadding = PaddingValues(8.dp), modifier = Modifier .fillMaxSize() .pullRefresh(pullToRefreshState), verticalArrangement = Arrangement.spacedBy(8.dp), ) { items(items) { content(it) } } PullRefreshIndicator( refreshing = isRefreshing, state = pullToRefreshState, modifier = Modifier.align(Alignment.TopCenter) ) }}

package com.example.swiperefresh
import android.os.Bundleimport androidx.activity.ComponentActivityimport androidx.activity.compose.setContentimport androidx.activity.enableEdgeToEdgeimport androidx.compose.foundation.layout.Arrangementimport androidx.compose.foundation.layout.Boximport androidx.compose.foundation.layout.PaddingValuesimport androidx.compose.foundation.layout.fillMaxSizeimport androidx.compose.foundation.layout.paddingimport androidx.compose.foundation.lazy.LazyColumnimport androidx.compose.foundation.lazy.LazyListStateimport androidx.compose.foundation.lazy.itemsimport androidx.compose.foundation.lazy.rememberLazyListStateimport androidx.compose.material3.ExperimentalMaterial3Apiimport androidx.compose.material3.Scaffoldimport androidx.compose.material3.Textimport androidx.compose.material3.pulltorefresh.PullToRefreshBoximport androidx.compose.material3.pulltorefresh.rememberPullToRefreshStateimport androidx.compose.runtime.Composableimport androidx.compose.runtime.getValueimport androidx.compose.runtime.mutableStateOfimport androidx.compose.runtime.rememberimport androidx.compose.runtime.rememberCoroutineScopeimport androidx.compose.runtime.setValueimport androidx.compose.ui.Alignmentimport androidx.compose.ui.Modifierimport androidx.compose.ui.unit.dpimport com.example.swiperefresh.ui.theme.SwipeRefreshThemeimport kotlinx.coroutines.delayimport kotlinx.coroutines.launch
class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { SwipeRefreshTheme { Scaffold(modifier = Modifier.fillMaxSize()) { innerPadding -> val items = remember { (1..100).map { "Item $it" } } var isRefreshing by remember { mutableStateOf(false) } val scope = rememberCoroutineScope()
Box( modifier = Modifier .fillMaxSize() .padding(innerPadding) ) { PullToRefreshLazyColumn( items = items, content = { Text(text = it) }, isRefreshing = isRefreshing, onRefresh = { scope.launch { isRefreshing = true delay(2000) isRefreshing = false } } ) } } } } }}
@OptIn(ExperimentalMaterial3Api::class)@Composablefun <T> PullToRefreshLazyColumn( items: List<T>, content: @Composable (T) -> Unit, isRefreshing: Boolean, onRefresh: () -> Unit, modifier: Modifier = Modifier, lazyListState: LazyListState = rememberLazyListState()) { val pullToRefreshState = rememberPullToRefreshState()
PullToRefreshBox( state = pullToRefreshState, modifier = modifier.fillMaxSize(), onRefresh = onRefresh, isRefreshing = isRefreshing, contentAlignment = Alignment.TopCenter, ) { LazyColumn( state = lazyListState, contentPadding = PaddingValues(8.dp), modifier = Modifier .fillMaxSize(), verticalArrangement = Arrangement.spacedBy(8.dp), ) { items(items) { content(it) } } }}