So implementieren Sie Android Pull-to-Refresh

433

Wenn Sie in Android-Anwendungen wie Twitter (offizielle App) auf eine ListView stoßen, können Sie diese nach unten ziehen (und sie wird bei der Veröffentlichung zurückspringen), um den Inhalt zu aktualisieren.

Ich frage mich, wie Sie das Ihrer Meinung nach am besten umsetzen können.

Einige Möglichkeiten, die mir einfallen könnten:

  1. Ein Element über der ListView - ich denke jedoch nicht, dass das Zurückblättern zu Elementposition 1 (0-basiert) mit Animation in der ListView eine einfache Aufgabe ist.
  2. Eine andere Ansicht außerhalb der ListView - aber ich muss darauf achten, dass die ListView-Position beim Ziehen nach unten verschoben wird, und ich bin nicht sicher, ob wir erkennen können, ob die Drag-Touch-Berührungen der ListView die Elemente in der ListView noch wirklich scrollen.

Irgendwelche Empfehlungen?

PS Ich frage mich, wann der offizielle Quellcode der Twitter-App veröffentlicht wird. Es wurde erwähnt, dass es veröffentlicht wird, aber 6 Monate sind vergangen und wir haben seitdem nichts mehr davon gehört.

Randy Sugianto 'Yuku'
quelle
Ist diese Funktionalität kann in einem dynamisch erstellten TableLayout implementiert werden. Bitte helfen Sie .....
Arun Badole
github.com/fruitranger/PulltorefreshListView ist eine weitere Implementierung von mir. Reibungslose und Multi-Touch-Unterstützung.
Changwei Yao
6
Verwandte Themen : „Pull-to-Refresh“: Ein Anti-UI-Muster unter Android ist ein Artikel, in dem argumentiert wird, dass diese Benutzeroberfläche nicht unter Android verwendet werden sollte, und der viele Diskussionen über ihre Angemessenheit ausgelöst hat.
Blahdiblah
29
Jemand sollte Google darüber informieren, da die neueste Version von Google Mail für Android dieses "Anti-Pattern" verwendet.
Nick
4
Pull to Refresh ist (und ist schon eine Weile) ein Standardmuster in iOS und Android und es ist sehr natürlich, so dass diese Anti-Pattern-Diskussion veraltet ist. Benutzer werden erwarten, es zu sehen und sich als solches zu verhalten.
Martin Marconcini

Antworten:

311

Schließlich hat Google eine offizielle Version der Pull-to-Refresh-Bibliothek veröffentlicht!

Es wird SwipeRefreshLayoutin der Support-Bibliothek aufgerufen und die Dokumentation finden Sie hier :

  1. Fügen Sie SwipeRefreshLayoutals Eltern betrachtet , die als Pull behandelt werden , um das Layout zu aktualisieren. (Ich habe ListViewals Beispiel, es kann beliebig sein , Viewwie LinearLayout, ScrollViewetc.)

    <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. Fügen Sie Ihrer Klasse einen Listener hinzu

    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);
            }
        });
    }

Sie können auch pullToRefresh.setRefreshing(true/false);nach Ihren Wünschen anrufen .

AKTUALISIEREN

Android-Unterstützungsbibliotheken sind veraltet und wurden durch AndroidX ersetzt. Den Link zur neuen Bibliothek finden Sie hier .

Außerdem müssen Sie Ihrem Projekt die folgende Abhängigkeit hinzufügen:

implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.0.0'

ODER

Sie können zu Refactor >> Migrate to AndroidX gehen und Android Studio übernimmt die Abhängigkeiten für Sie.

Randy Sugianto 'Yuku'
quelle
3
Kann ich in SwipeRefreshLayout eine ProgressBar anstelle eines Farbschemas verwenden?
Pablobaldez
54
1. April 14 - und das war kein Scherz
Aeracode
80

Ich habe versucht, eine Pull-to-Refresh-Komponente zu implementieren. Sie ist bei weitem nicht vollständig , zeigt jedoch eine mögliche Implementierung, https://github.com/johannilsson/android-pulltorefresh .

Die Hauptlogik ist in PullToRefreshListViewdieser Erweiterung implementiert ListView. Intern wird das Scrollen einer Header-Ansicht mithilfe von smoothScrollBy(API Level 8) gesteuert. Das Widget wurde jetzt mit Unterstützung für 1.5 und höher aktualisiert. Bitte lesen Sie jedoch die README for 1.5-Unterstützung.

In Ihren Layouts fügen Sie es einfach so hinzu.

<com.markupartist.android.widget.PullToRefreshListView
    android:id="@+id/android:list"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    />
Johan Berg Nilsson
quelle
3
Hallo johan, ich habe deinen Beispielcode heruntergeladen. Es funktioniert in Android 2.2 Gerät, aber nicht in 2.1 Gerät. Ich denke, weil es SmoothScrollBy- Methode verwendet, die nur in 2.2 oder höher verfügbar ist, ist richtig? Und haben Sie eine Idee, diesen Effekt in 2.1 oder einer früheren Version zu implementieren? Danke
Ja, das ist richtig, wie ich in der Antwort angegeben habe. SmoothScrollBy wurde in API Level 8 (2.2) eingeführt. Ich habe noch keinen geeigneten Weg gefunden, um es für andere Versionen zu implementieren, aber es sollte möglich sein, die Implementierung von SmoothScrollBy zu portieren, aber ich denke, dass die Diskussion am Projektstandort und nicht beim Stapelüberlauf fortgesetzt werden sollte.
Johan Berg Nilsson
Ist es absichtlich so, dass die ID @ + id / android: list und nicht @android: id / list ist, es sieht komisch aus? Das Projekt wirft hier einen Inflationsfehler auf meine Seite, das überprüfe ich gerade ...
Mathias Conradt
12
Dies ist die beste Bibliothek zum Ziehen, um sie zu aktualisieren . Github.com/chrisbanes/Android-PullToRefresh . Es funktioniert mit ListViews, GridViews und Webviews. Hat auch Pull-up zum Aktualisieren des Musters implementiert.
rOrlig
1
Wie füge ich das Projekt in den Bibliotheksordner ein, während ich an Intellij Idea arbeite? Kann mir jemand helfen?
Mustafa Güven
55

Ich habe auch eine robuste, Open Source, benutzerfreundliche und hochgradig anpassbare PullToRefresh-Bibliothek für Android implementiert. Sie können Ihre ListView durch die PullToRefreshListView ersetzen, wie in der Dokumentation auf der Projektseite beschrieben.

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

Erik
quelle
Ich habe alle hier aufgeführten Implementierungen ausprobiert und Ihre ist die beste, was das einfache / reine / reibungslose Ziehen zum Aktualisieren der Implementierung betrifft (kein Tippen zum Aktualisieren der Verrücktheit wie bei Johans). Vielen Dank!
Gady
1
Kann dies eine Standard-ListView ersetzen, um mit ListActivity, ListFragment usw. zu arbeiten?
Davidcesarino
Ja, geben Sie dem PullToRefreshListView einfach die richtige ID. In XML: android: id = "@ android: id / list"
Erik
1
das ist absolut genial! Google hat mich hierher gebracht, und wenn Sie sich die Beispiele ansehen, ist Ihr Aussehen am einfachsten zu implementieren. Bravo und danke, Sir!
Evan R.
Sehr vernünftig gestaltete Komponente, schön und einfach. Dies sollte definitiv die akzeptierte Antwort sein.
Adam
41

Ich denke, der einfachste Weg ist der, den die Android-Support-Bibliothek bietet:

android.support.v4.widget.SwipeRefreshLayout;

Sobald dies importiert ist, können Sie Ihr Layout wie folgt definieren:

  <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>

Ich gehe davon aus, dass Sie die Recycler-Ansicht anstelle der Listenansicht verwenden. Die Listenansicht funktioniert jedoch weiterhin, sodass Sie nur die Recyclingansicht durch die Listenansicht ersetzen und die Verweise im Java-Code (Fragment) aktualisieren müssen.

In Ihrem Aktivitätsfragment implementieren Sie zuerst die Schnittstelle. 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);

   }
}

Hoffe das hilft den Massen

larrytech
quelle
Es funktioniert gut. Eines jedoch in Bezug auf setRefreshing: "Rufen Sie dies nicht auf, wenn die Aktualisierung durch eine Wischgeste ausgelöst wird", wie in developer.android.com/reference/android/support/v4/widget/…
gabriel14,
Gut gemacht! Vielen Dank.
Technik
22

In diesem Link finden Sie eine Abzweigung der berühmten PullToRefreshAnsicht, die neue interessante Implementierungen wie PullTorRefreshWebViewoder PullToRefreshGridViewoder die Möglichkeit enthält, eine PullToRefresham unteren Rand einer Liste hinzuzufügen .

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

Und das Beste daran ist, dass es in Android 4.1 perfekt funktioniert (das Normale PullToRefreshfunktioniert nicht).

Aracem
quelle
3
Ein großer Kommentar oben in der Readme-Datei zeigt an: DIESES PROJEKT WIRD NICHT MEHR GEWARTET. Wie auch immer, diese Bibliothek ist die beste, die ich bisher gesehen habe! Gute Arbeit!
Milton
3
Nur weil es nicht mehr gewartet wird, heißt das nicht, dass es nicht gut ist. Verwenden Sie es immer noch für alle meine Pull, um Bedürfnisse zu aktualisieren :)
Muz
18

Ich habe eine sehr einfache Möglichkeit, dies zu tun, aber jetzt ist es sicher die narrensichere Möglichkeit. Es gibt meinen Code 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;
    }
}

Sie müssen lediglich ListViewTouchEventListener in Ihrer Aktivität implementieren, in der Sie diese ListView verwenden möchten, und den Listener festlegen

Ich habe es in PullDownListViewActivity implementiert

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");
    }
}

Für mich geht das :)

Pushpan
quelle
18

Um Android Pull-to-Refresh zu implementieren, versuchen Sie diesen Code,

<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>

Aktivitätsklasse:

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);

 }
Mani
quelle
1
Thanks.it hat mir wirklich geholfen
Arpan Sharma
9

Niemand hat die neue Art von "Zum Aktualisieren ziehen" erwähnt, die wie in der Google Now- oder Google Mail-Anwendung über der Aktionsleiste angezeigt wird.

Es gibt eine Bibliothek ActionBar-PullToRefresh, die genauso funktioniert.

Tomrozb
quelle
7

Beachten Sie, dass bei der Implementierung unter Android und WP UX-Probleme auftreten.

"Ein guter Indikator dafür, warum Designer / Entwickler Pull-to-Refresh nicht im Stil von iOS-Apps implementieren sollten, ist, wie Google und seine Teams Pull-to-Refresh unter Android niemals verwenden, während sie es unter iOS verwenden."

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

Uobroin
quelle
3
Ich weiß, dass dies über ein Jahr alt ist, aber die Google Mail-App verwendet Pull-to-Refresh. In Bezug auf die Benutzeroberfläche ist dies jedoch nicht genau dasselbe. Die Liste wird nicht nach unten gescrollt, sondern eine neue Ansicht wird oben auf dem Bildschirm angezeigt.
Ashishduh
4

Wenn Sie nicht möchten, dass Ihr Programm wie ein iPhone-Programm aussieht, das zwangsweise in Android integriert ist, streben Sie ein nativeres Erscheinungsbild an und tun Sie etwas Ähnliches wie Lebkuchen:

Alt-Text

Lie Ryan
quelle
2
@Rob: Ich meinte, den orangefarbenen Schatten oben auf der Liste zu haben, wenn Sie überziehen, anstatt die Liste wie auf dem iPhone zurückspringen zu lassen. Dies ist als Kommentar gedacht (keine Antwort), aber Kommentare können keine Bilder enthalten.
Lie Ryan
Ahh, sorry, tolle Idee. Ich habe noch nicht mit Lebkuchen gespielt, also hatte ich den Effekt nicht gesehen. Ich warte immer noch darauf, dass Google es auf den Nexus rollt.
Rob
9
Ich habe Lebkuchen und das orange Leuchten funktioniert gut, wenn eine Liste statisch ist. Die Pulldown-Aktualisierung ist jedoch ein großartiger UI-Mechanismus, um eine dynamische Liste zu aktualisieren. Obwohl es in der iOS-Welt weit verbreitet ist, ist es ein UI-Trick, der sich im Android-Ökosystem nicht seltsam anfühlt. Ich empfehle dringend, dass Sie es in der offiziellen Twitter-App überprüfen. :)
Thierry-Dimitri Roy
Das native Verhalten hier zeigt an, dass Sie das Ende einer Liste erreicht haben. Dies zu nehmen und eine Aktualisierung durchzuführen, ist identisch nicht nativ, da Sie nicht das tun, was die Plattform tut. Dies bedeutet, dass Sie den Benutzer eher überraschen. Ich würde sicherlich keine Aktualisierung erwarten oder wollen, nur weil ich am Ende einer Liste angekommen bin. Zum Aktualisieren nach unten ziehen ist viel intuitiver und klarer. Und da die native Twitter-App sie verwendet, ist es meiner Meinung nach fair zu sagen, dass es sich um ein UI-Konzept handelt, mit dem viele Menschen vertraut sind.
Stiefschrank
4

Ich habe hier eine Pull-to-Refresh-Komponente geschrieben: https://github.com/guillep/PullToRefresh Es funktioniert, wenn die Liste keine Elemente enthält, und ich habe sie auf> = 1.6 Android-Handys getestet.

Jeder Vorschlag oder jede Verbesserung wird geschätzt :)

Guille Polito
quelle
1

So erhalten Sie die neueste Lollipop Pull-To-Aktualisierung:

  1. Laden Sie das neueste Lollipop SDK und die Extras / Android-Supportbibliothek herunter
  2. Setzen Sie das Build-Ziel des Projekts auf Android 5.0 (andernfalls kann das Support-Paket Fehler mit Ressourcen aufweisen).
  3. Aktualisieren Sie Ihre libs / android-support-v4.jar auf die 21. Version
  4. Verwenden Sie android.support.v4.widget.SwipeRefreshLayoutplusandroid.support.v4.widget.SwipeRefreshLayout.OnRefreshListener

Eine ausführliche Anleitung finden Sie hier: http://antonioleiva.com/swiperefreshlayout/

Plus für ListView empfehle ich canChildScrollUp()in den Kommentaren zu lesen ;)

goRGon
quelle
Plus eine nur für die Erwähnung von canChildScrollUp (). Sehr wichtig!
Petro
1

Sehr interessanter Pull-to-Refresh von Yalantis . Gif für iOS, aber du kannst es überprüfen :)

<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" />

edbaev
quelle
0

Wir sollten zuerst wissen, was Pull ist, um das Layout in Android zu aktualisieren. Wir können Pull zum Aktualisieren in Android als Swipe-to-Refresh aufrufen. Wenn Sie den Bildschirm von oben nach unten streichen, wird eine Aktion basierend auf setOnRefreshListener ausgeführt.

Hier ist ein Tutorial , das zeigt, wie man Android Pull zum Aktualisieren implementiert. Ich hoffe das hilft.

Hasan Raza
quelle