453 votos

Cómo implementar Android Pull-to-Refresh

En las aplicaciones de Android, como Twitter (aplicación oficial), cuando se encuentra un ListView, se puede tirar de él hacia abajo (y volverá a rebotar cuando se suelte) para refrescar el contenido.

Me pregunto cuál es la mejor manera, en su opinión, de aplicarlo.

Algunas posibilidades que se me ocurren:

  1. Un elemento en la parte superior del ListView - sin embargo no creo que el desplazamiento hacia atrás a la posición del elemento 1 (basado en 0) con la animación en el ListView sea una tarea fácil.
  2. Otra vista fuera de la ListView - pero tengo que cuidar de mover la posición de la ListView hacia abajo cuando se tira, y no estoy seguro de si podemos detectar si los toques de arrastre a la ListView todavía realmente desplazar los elementos en la ListView.

¿Alguna recomendación?

P.D. Me pregunto cuándo se liberará el código fuente de la aplicación oficial de Twitter. Se ha mencionado que será liberado, pero han pasado 6 meses y no hemos oído hablar de ello desde entonces.

0 votos

Es esta funcionalidad se puede implementar en un TableLayout creado dinámicamente. Por favor, ayuda .....

0 votos

github.com/fruitranger/PulltorefreshListView es otra implementación mía. Suave y con soporte multitáctil.

6 votos

Relacionado: "Pull-to-refresh": un patrón anti UI en Android es un artículo en el que se argumenta que esta IU no es algo que debería usarse en Android y provocó un gran debate sobre su conveniencia.

342voto

yuku Puntos 15705

Por fin, Google ha lanzado una versión oficial de la biblioteca pull-to-refresh.

Se llama SwipeRefreshLayout dentro de la biblioteca de apoyo, y la documentación es aquí :

  1. Añadir SwipeRefreshLayout como padre de la vista que será tratada como un pull para refrescar el diseño. (He tomado ListView como ejemplo, puede ser cualquier View como LinearLayout , ScrollView etc.)

    <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/pullToRefresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">
        <ListView
            android:id="@+id/listView"
            android:layout_width="match_parent"
            android:layout_height="match_parent"/>
    </android.support.v4.widget.SwipeRefreshLayout>
  2. Añade un oyente a tu clase

    protected void onCreate(Bundle savedInstanceState) {
        final SwipeRefreshLayout pullToRefresh = findViewById(R.id.pullToRefresh);
        pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                refreshData(); // your code
                pullToRefresh.setRefreshing(false);
            }
        });
    }

También puede llamar a pullToRefresh.setRefreshing(true/false); según sus necesidades.

ACTUALIZACIÓN

Las librerías de soporte de Android han quedado obsoletas y han sido sustituidas por AndroidX. El enlace a la nueva biblioteca se puede encontrar aquí .

Además, debe añadir la siguiente dependencia a su proyecto:

implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'

O

Puedes ir a Refactor>>Migrar a AndroidX y Android Studio se encargará de las dependencias por ti.

3 votos

¿Puedo utilizar una barra de progreso en lugar de un esquema de color en SwipeRefreshLayout?

58 votos

1 de abril '14 - y eso no era una broma

2 votos

80voto

Johan Nilsson Puntos 1224

He hecho un intento de implementar un componente de pull to refresh, es lejos de estar completo pero demuestra una posible implementación, https://github.com/johannilsson/Android-pulltorefresh .

La lógica principal se implementa en PullToRefreshListView que se extiende ListView . Internamente controla el desplazamiento de una vista de cabecera utilizando smoothScrollBy (Nivel 8 de la API). El widget está ahora actualizado con soporte para 1.5 y posteriores, por favor lee el README para el soporte de 1.5.

En tus diseños simplemente lo añades así.

<com.markupartist.android.widget.PullToRefreshListView
    android:id="@+id/android:list"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    />

3 votos

Hola johan, he descargado tu código de ejemplo. Funciona en el dispositivo Android 2.2 pero no funciona en el dispositivo 2.1. Creo que porque se utiliza smoothScrollBy que sólo está disponible en 2.2 o posterior, ¿es correcto? ¿Y tienes alguna idea para implementar este efecto en la versión 2.1 o anterior? Gracias

0 votos

Sí, eso es correcto, como dije en la respuesta, smoothScrollBy se introdujo en el nivel 8 de la API (2.2). Todavía no he encontrado una forma adecuada de implementarlo para otras versiones, pero supongo que debería ser posible portar la implementación de smoothScrollBy, pero supongo que la discusión debe mantenerse en el sitio del proyecto y no en stack overflow.

0 votos

¿Es a propósito que el id sea @+id/Android:list y no @Android:id/list, se ve raro? El proyecto arroja un error de inflación aquí en mi lado, estoy comprobando en eso...

55voto

Erik Puntos 2065

También he implementado una biblioteca PullToRefresh robusta, de código abierto, fácil de usar y altamente personalizable para Android. Puedes reemplazar tu ListView con el PullToRefreshListView como se describe en la documentación de la página del proyecto.

https://github.com/erikwt/PullToRefresh-ListView

0 votos

He probado todas las implementaciones listadas aquí y la tuya es la mejor, en términos de una implementación simple/pura/suave de pull to refresh (sin rarezas de tap to refresh como la de Johan). Gracias.

1 votos

¿Puede esto sustituir a un ListView estándar para trabajar con ListActivity, ListFragment y demás?

0 votos

Sí, sólo hay que darle al PullToRefreshListView el id correcto. En XML: Android:id="@Android:id/list"

23voto

Aracem Puntos 3331

En este enlace, puede encontrar una bifurcación del famoso PullToRefresh que tiene nuevas e interesantes implementaciones como PullTorRefreshWebView o PullToRefreshGridView o la posibilidad de añadir un PullToRefresh en el borde inferior de una lista.

https://github.com/chrisbanes/Android-PullToRefresh

Y lo mejor de todo es que funcionan perfectamente en Android 4.1 (el normal PullToRefresh no funciona )

3 votos

Un gran comentario en la parte superior del readme indica: ESTE PROYECTO YA NO SE MANTIENE. De todos modos, ¡esta librería es la mejor que he visto hasta ahora! ¡Gran trabajo!

3 votos

El hecho de que ya no se mantenga, no significa que no sea bueno. Todavía lo uso para todas mis necesidades de refresco :)

18voto

Pushpan Puntos 209

Tengo una manera muy fácil de hacer esto, pero ahora estoy seguro de que es la manera infalible Este es mi código PullDownListView.java

package com.myproject.widgets;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ListView;

/**
 * @author Pushpan
 * @date Nov 27, 2012
 **/
public class PullDownListView extends ListView implements OnScrollListener {

    private ListViewTouchEventListener mTouchListener;
    private boolean pulledDown;

    public PullDownListView(Context context) {
        super(context);
        init();
    }

    public PullDownListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public PullDownListView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        setOnScrollListener(this);
    }

    private float lastY;

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            lastY = ev.getRawY();
        } else if (ev.getAction() == MotionEvent.ACTION_MOVE) {
            float newY = ev.getRawY();
            setPulledDown((newY - lastY) > 0);
            postDelayed(new Runnable() {
                @Override
                public void run() {
                    if (isPulledDown()) {
                        if (mTouchListener != null) {
                            mTouchListener.onListViewPulledDown();
                            setPulledDown(false);
                        }
                    }
                }
            }, 400);
            lastY = newY;
        } else if (ev.getAction() == MotionEvent.ACTION_UP) {
            lastY = 0;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        setPulledDown(false);
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
    }

    public interface ListViewTouchEventListener {
        public void onListViewPulledDown();
    }

    public void setListViewTouchListener(
            ListViewTouchEventListener touchListener) {
        this.mTouchListener = touchListener;
    }

    public ListViewTouchEventListener getListViewTouchListener() {
        return mTouchListener;
    }

    public boolean isPulledDown() {
        return pulledDown;
    }

    public void setPulledDown(boolean pulledDown) {
        this.pulledDown = pulledDown;
    }
}

Sólo tienes que implementar ListViewTouchEventListener en tu actividad en la que quieras utilizar este ListView y establecer el listener

Lo tengo implementado en PullDownListViewActivity

package com.myproject.activities;

import android.app.Activity;
import android.os.Bundle;

/**
 * @author Pushpan
 *
 */
public class PullDownListViewActivity extends Activity implements ListViewTouchEventListener {

    private PullDownListView listView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        listView = new PullDownListView(this);
        setContentView(listView);
        listView.setListViewTouchListener(this);

        //setItems in listview
    }

    public void onListViewPulledDown(){
        Log.("PullDownListViewActivity", "ListView pulled down");
    }
}

A mí me funciona :)

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X