Cómo implementar Android Pull-to-Refresh


En aplicaciones Android como Twitter (aplicación oficial), cuando se encuentra con una vista de lista, se puede tirar hacia abajo (y se recuperará cuando se lance) para actualizar el contenido.

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

Algunas posibilidades que se me ocurren:

  1. Un elemento en la parte superior de la ListView - sin embargo, no creo que desplazarse hacia atrás a la posición del elemento 1 (basado en 0) con animación en la 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 desplazan los elementos en la ListView.

Alguna recomendación?

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

Author: Michael Celey, 2011-01-03

14 answers

Finalmente, Google lanzó una versión oficial de la biblioteca pull-to-refresh!

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

1) Agregue SwipeRefreshLayout como un padre de la vista que se tratará como pull para actualizar el diseño. (Tomé 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) Agregar un oyente a su clase

protected void onCreate(Bundle savedInstanceState) {
    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 su requisito.

 216
Author: Randy Sugianto 'Yuku',
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-10 15:57:20

He hecho un intento de implementar un componente pull to refresh, está lejos de completarse 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 encabezado usando smoothScrollBy (Nivel de API 8). El widget ahora se actualiza con soporte para 1.5 y posteriores, por favor lea el README para soporte 1.5 sin embargo.

En su diseños que simplemente añadir como este.

<com.markupartist.android.widget.PullToRefreshListView
    android:id="@+id/android:list"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    />
 78
Author: Johan Berg Nilsson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-24 16:00:03

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

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

 53
Author: Erik,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-07 02:03:24

La forma más fácil creo que es la proporcionada por la biblioteca de soporte de Android:

Android.apoyo.v4.widget.SwipeRefreshLayout;

Una vez que se importa, puede tener su diseño definido de la siguiente manera:

  <android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/refresh"
        android:layout_height="match_parent"
        android:layout_width="match_parent">
    <android.support.v7.widget.RecyclerView
        xmlns:recycler_view="http://schemas.android.com/apk/res-auto"
        android:id="@android:id/list"
        android:theme="@style/Theme.AppCompat.Light"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/button_material_light"
        >

    </android.support.v7.widget.RecyclerView>
</android.support.v4.widget.SwipeRefreshLayout>

Asumo que utilizas la vista recycler en lugar de listview. Sin embargo, listview todavía funciona, por lo que solo necesita reemplazar recyclerview con listview y actualizar las referencias en el código java (Fragmento).

En su fragmento de actividad, primero implementa interfaz, SwipeRefreshLayout.OnRefreshListener: i, e

public class MySwipeFragment extends Fragment implements SwipeRefreshLayout.OnRefreshListener{
private SwipeRefreshLayout swipeRefreshLayout;

@Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.fragment_item, container, false);
        swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.refresh);
        swipeRefreshLayout.setOnRefreshListener(this);
}


 @Override
  public void onRefresh(){
     swipeRefreshLayout.setRefreshing(true);
     refreshList();
  }
  refreshList(){
    //do processing to get new data and set your listview's adapter, maybe  reinitialise the loaders you may be using or so
   //when your data has finished loading, cset the refresh state of the view to false
   swipeRefreshLayout.setRefreshing(false);

   }
}

Espero que esto ayude a las masas

 35
Author: larrytech,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-15 18:28:08

En este enlace, puedes encontrar una bifurcación de la famosa vista PullToRefresh que tiene nuevas implementaciones interesantes como PullTorRefreshWebView o PullToRefreshGridView o la posibilidad de agregar un PullToRefresh en el borde inferior de una lista.

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

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

 21
Author: Aracem,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-10 14:48:33

Tengo una manera muy fácil de hacer esto, pero ahora seguro que es la manera infalible Ahí está 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;
    }
}

Solo necesita implementar ListViewTouchEventListener en su actividad donde desea usar 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");
    }
}

Funciona para mí:)

 18
Author: Pushpan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-11-27 11:45:02

Para implementar android Pull-to-Refresh pruebe esta pieza de código,

<android.support.v4.widget.SwipeRefreshLayout
        android:id="@+id/pullToRefresh"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >
    </ListView>

</android.support.v4.widget.SwipeRefreshLayout>

Clase de actividad:

ListView lv = (ListView) findViewById(R.id.lv);
SwipeRefreshLayout pullToRefresh = (SwipeRefreshLayout) findViewById(R.id.pullToRefresh);


lv.setAdapter(mAdapter);

pullToRefresh.setOnRefreshListener(new OnRefreshListener() {

        @Override
        public void onRefresh() {
            // TODO Auto-generated method stub

            refreshContent();

        }
    });



private void refreshContent(){ 

     new Handler().postDelayed(new Runnable() {
            @Override public void run() {
                pullToRefresh.setRefreshing(false);
            }
        }, 5000);

 }
 18
Author: mani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-20 08:51:10

Nadie ha mencionado el nuevo tipo de "Pull to refresh" que se muestra en la parte superior de la barra de acciones como en la aplicación Google Now o Gmail.

Existe una biblioteca ActionBar-PullToRefresh que funciona exactamente igual.

 9
Author: tomrozb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-12-21 11:10:31

Tenga en cuenta que hay problemas de UX con los que lidiar al implementar en Android y WP.

"Un gran indicador de por qué los diseñadores/desarrolladores no deben implementar pull-to-refresh en el estilo que hacen las aplicaciones de iOS es cómo Google y sus equipos nunca usan pull-to-refresh en Android mientras lo usan en iOS. "

Https://plus.google.com/109453683460749241197/posts/eqYxXR8L4eb

 7
Author: uobroin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-23 20:09:02

Si no quieres que tu programa se vea como un programa de iPhone que se ajusta a la fuerza en Android, busca un aspecto más nativo y haz algo similar a Gingerbread:

texto alt

 4
Author: Lie Ryan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-01-05 14:34:28

He escrito un pull para actualizar el componente aquí: https://github.com/guillep/PullToRefresh Funciona evento si la lista no tiene elementos, y lo he probado en >=1.6 teléfonos android.

Cualquier sugerencia o mejora es apreciada:)

 4
Author: Guille Polito,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-30 20:05:21

Creo que la mejor biblioteca es : https://github.com/chrisbanes/Android-PullToRefresh.

Funciona con:

ListView
ExpandableListView
GridView
WebView
ScrollView
HorizontalScrollView
ViewPager
 2
Author: Jossy Paul,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-25 05:13:24

Para obtener el último Pull de piruleta-Para Actualizar:

  1. Descargue la última Lollipop SDK y Extras / Biblioteca de soporte de Android
  2. Establezca el objetivo de compilación del proyecto en Android 5.0 (de lo contrario, el paquete de soporte puede tener errores con los recursos)
  3. Actualiza tu libs/android-support-v4.jar to 21st version
  4. Use android.support.v4.widget.SwipeRefreshLayout más android.support.v4.widget.SwipeRefreshLayout.OnRefreshListener

Se puede encontrar una guía detallada aquí: http://antonioleiva.com/swiperefreshlayout /

Más para ListView Recomiendo lea acerca de canChildScrollUp() en los comentarios;)

 1
Author: goRGon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-11-19 20:34:45

Muy interesante Pull-to-Refresh por Yalantis. Gif para iOS, pero puedes comprobarlo:)

<com.yalantis.pulltorefresh.library.PullToRefreshView
android:id="@+id/pull_to_refresh"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ListView
    android:id="@+id/list_view"
    android:divider="@null"
    android:dividerHeight="0dp"
    android:layout_width="match_parent"
    android:layout_height="match_parent" />

 1
Author: edbaev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-01-19 13:42:39