如何实现Android Pull-to-Refresh

时间:2011-01-03 09:51:23

标签: android listview android-listview pull-to-refresh

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

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

我能想到的一些可能性:

  1. ListView顶部的项目 - 但是我不认为在ListView上使用动画滚动回项目位置1(从0开始)是一件容易的事。
  2. ListView之外的另一个视图 - 但我需要注意在拉动时将ListView位置向下移动,我不确定我们是否可以检测到ListView的拖动是否仍然真正滚动项目ListView。
  3. 有什么建议吗?

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

16 个答案:

答案 0 :(得分:253)

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

在支持库中称为SwipeRefreshLayout,文档为here

1)添加SwipeRefreshLayout作为视图的父级,将其视为拉动刷新布局。 (我以ListView为例,它可以是ViewLinearLayoutScrollView等。

<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)为您的班级添加听众

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

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

答案 1 :(得分:79)

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

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

在你的布局中,你只需像这样添加它。

smoothScrollBy

答案 2 :(得分:54)

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

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

答案 3 :(得分:36)

我认为最简单的方法是由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>

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

在您的活动片段中,首先实现界面SwipeRefreshLayout.OnRefreshListener: 我,是

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

   }
}

希望这有助于群众

答案 4 :(得分:21)

在此链接中,您可以找到着名的PullToRefresh视图的分支,其中包含PullTorRefreshWebViewPullToRefreshGridView等新的有趣实施,或者可以添加PullToRefresh列表的下边缘。

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

最好的是Android 4.1中的完美工作(正常的PullToRefresh无法正常工作)

答案 5 :(得分: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;
    }
}

您只需要在您要使用此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");
    }
}

它对我有用:)

答案 6 :(得分: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>

活动类:

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

 }

答案 7 :(得分:9)

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

有一个库ActionBar-PullToRefresh完全相同。

答案 8 :(得分:7)

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

“一个很好的指标,说明为什么设计师/开发人员不应该在iOS应用程序风格中实现拉动刷新,这是Google及其团队在iOS上使用它时从不在Android上使用pull-to-refresh的方式。”

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

答案 9 :(得分:4)

如果您不希望自己的程序看起来像是强制安装到Android中的iPhone程序,那么可以采用更原生的外观和感觉来做类似姜饼的事情:

alt text

答案 10 :(得分:4)

我在这里写了一个提拉刷新组件:https://github.com/guillep/PullToRefresh 如果列表没有项目,它会工作,我在&gt; = 1.6安卓手机上测试了它。

任何建议或改进都表示赞赏:)

答案 11 :(得分:2)

我认为最好的图书馆是:https://github.com/chrisbanes/Android-PullToRefresh

适用于:

ListView
ExpandableListView
GridView
WebView
ScrollView
HorizontalScrollView
ViewPager

答案 12 :(得分:1)

获取最新的Lollipop Pull-To Refresh:

  1. 下载最新的Lollipop SDK和Extras / Android支持库
  2. 将Project的Build Target设置为Android 5.0(否则支持包可能会出现资源错误)
  3. 将您的libs / android-support-v4.jar更新为第21版
  4. 使用android.support.v4.widget.SwipeRefreshLayoutandroid.support.v4.widget.SwipeRefreshLayout.OnRefreshListener
  5. 详细指南可在此处找到:http://antonioleiva.com/swiperefreshlayout/

    对于ListView,我建议在评论中阅读canChildScrollUp();)

答案 13 :(得分:1)

Pull-to-Refresh非常有趣Yalantis。 适用于iOS的Gif,但您可以查看它:)

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

答案 14 :(得分:0)

我们首先应该知道什么是Pull来刷新android中的布局。我们可以调用pull在Android中刷新为刷卡刷新。当您从上到下滑动屏幕时,它将基于setOnRefreshListener进行一些操作。

这里的tutorial演示了如何实现android pull刷新。我希望这会有所帮助。

答案 15 :(得分:0)

希望为 RecyclerView 实现拉动刷新功能的用户可以按照我的简单教程How to implement Pull To Refresh for RecyclerView in Android进行操作。

要导入的库

.npmignore

XML代码

implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'androidx.gridlayout:gridlayout:1.0.0'

活动JAVA代码

<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
    android:id="@+id/swipe_layout"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>