如何实现Android Pull-to-Refresh

Ran*_*ku' 414 android listview android-listview pull-to-refresh

在Twitter(官方应用程序)等Android应用程序中,当您遇到ListView时,可以将其拉下(并在发布时它会反弹)以刷新内容.

我想知道在您看来,实施该方法的最佳方式是什么?

我能想到的一些可能性:

  1. ListView顶部的项目 - 但我不认为在ListView上使用动画滚动回项目位置1(从0开始)是一项简单的任务.
  2. ListView之外的另一个视图 - 但我需要注意在拉动时向下移动ListView位置,我不确定我们是否可以检测到ListView的拖动是否仍然真正滚动ListView上的项目.

有什么建议?

PS我想知道官方Twitter应用程序源代码何时发布.有人提到它会被释放,但已经过去了6个月,从那时起我们就没有听说过.

Ran*_*ku' 278

最后,Google发布了一个正式版的pull-to-refresh库!

SwipeRefreshLayout在支持库中被调用,文档在这里:

1)添加SwipeRefreshLayout为视图的父级,将被视为拉动刷新布局.(我ListView举了一个例子,它可以是任何ViewLinearLayout,ScrollView等等)

<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>
Run Code Online (Sandbox Code Playgroud)

2)为你的班级添加一个听众

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);
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

您也可以pullToRefresh.setRefreshing(true/false);根据您的要求致电.

  • _Apr 1'14_ - 这不是开玩笑 (49认同)
  • 我可以在SwipeRefreshLayout上使用ProgressBar而不是Color Scheme吗? (3认同)
  • 示例代码https://guides.codepath.com/android/Implementing-Pull-to-Refresh-Guide (2认同)

Joh*_*son 79

我已尝试实现一个pull to refresh组件,它远未完成,但演示了一个可能的实现,https://github.com/johannilsson/android-pulltorefresh.

主要逻辑在PullToRefreshListView该扩展中实现ListView.在内部,它使用smoothScrollBy(API级别8)控制标题视图的滚动.现在更新了小部件,支持1.5及更高版本,请阅读README以获得1.5支持.

在您的布局中,您只需像这样添加它.

<com.markupartist.android.widget.PullToRefreshListView
    android:id="@+id/android:list"
    android:layout_height="fill_parent"
    android:layout_width="fill_parent"
    />
Run Code Online (Sandbox Code Playgroud)

  • 这是我发现的最好的刷新库..https://github.com/chrisbanes/Android-PullToRefresh.它适用于ListViews,GridViews和Webview.还有拉起来实现刷新模式. (12认同)
  • 嗨johan,我已经下载了你的示例代码.它在Android 2.2设备中工作,但在2.1设备中没有工作.我认为因为它使用了**smoothScrollBy**方法,只能在2.2或更高版本中使用,是否正确?您是否有任何想法将此效果实现到2.1或更早版本?谢谢 (3认同)

Eri*_*rik 54

我还为Android实现了一个强大的,开源的,易于使用且高度可定制的PullToRefresh库.您可以使用PullToRefreshListView替换ListView,如项目页面上的文档中所述.

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


lar*_*ech 38

我认为最简单的方法是由android支持库提供:

android.support.v4.widget.SwipeRefreshLayout;

一旦导入,您可以按如下方式定义您的布局:

  <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>
Run Code Online (Sandbox Code Playgroud)

我假设您使用recycleler视图而不是listview.但是,listview仍然有效,所以你只需要用listview替换recyclerview并更新java代码(Fragment)中的引用.

在您的活动片段中,首先实现接口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);

   }
}
Run Code Online (Sandbox Code Playgroud)

希望这有助于群众


Ara*_*cem 21

在这个链接中,你可以找到一个着名PullToRefresh视图的分支,它有一些新的有趣的实现,PullTorRefreshWebView或者PullToRefreshGridView可以在PullToRefresh列表的下边缘添加一个.

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

最好的是Android 4.1中完美的工作(正常PullToRefresh不起作用)

  • 自述文件顶部的一个重要评论表明:此项目不再受到维护.无论如何,这个lib是迄今为止我见过的最好的lib!做得好! (3认同)
  • 仅仅因为它不再被维护,并不意味着它不好.仍然使用它来满足我所有的刷新需求:) (3认同)

小智 18

我有非常简单的方法来做到这一点,但现在确定它的万无一失的方式有我的代码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;
    }
}
Run Code Online (Sandbox Code Playgroud)

您只需要在您要使用此ListView的活动上实现ListViewTouchEventListener并设置监听器

我在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");
    }
}
Run Code Online (Sandbox Code Playgroud)

这个对我有用 :)


man*_*ani 18

要实现android Pull-to-Refresh尝试这段代码,

<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>
Run Code Online (Sandbox Code Playgroud)

活动类:

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

 }
Run Code Online (Sandbox Code Playgroud)


tom*_*ozb 9

没有人提到新的"拉动刷新"类型,它显示在操作栏的顶部,就像在Google即时或Gmail应用程序中一样.

ActionBar-PullToRefresh库有一个完全相同的工作原理.


小智 7

请注意,在Android和WP上实现时,需要解决UX问题.

"对于为什么设计师/开发人员不应该在iOS应用程序风格中实现拉动刷新的一个很好的指标是Google和他们的团队在iOS上使用它时从不使用Android上的pull-to-refresh."

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

  • 我知道这已经超过一年了,但Gmail应用确实使用了pull-to-refresh.然而,就UI而言,它并不完全相同,列表不向下滚动,而是在屏幕顶部显示新视图. (3认同)