在Twitter(官方应用)等Android应用中,当你遇到一个ListView时,你可以下拉它(它会在发布时反弹)来刷新内容。

我想知道,在你看来,最好的实现方式是什么?

我能想到的一些可能性:

一个在ListView顶部的项目-然而我不认为滚动回项目位置1(基于0)在ListView上的动画是一个简单的任务。 ListView之外的另一个视图-但我需要注意在它被拉时将ListView位置向下移动,我不确定我们是否可以检测到对ListView的拖动触摸是否仍然真正滚动ListView上的项。

你有什么推荐吗?

另外,我想知道官方的Twitter应用程序源代码什么时候发布。有消息说它会发布,但6个月过去了,我们一直没有听到它的消息。


如果你不想让你的程序看起来像一个强行安装在Android上的iPhone程序,目标是一个更原生的外观和感觉,并做一些类似于Gingerbread的事情:


我已经尝试实现一个拉刷新组件,它还远远没有完成,但演示了一个可能的实现,https://github.com/johannilsson/android-pulltorefresh。

主要逻辑在扩展ListView的PullToRefreshListView中实现。在内部,它使用smoothScrollBy (API Level 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"
    />

我在这里写了一个拉取刷新组件:https://github.com/guillep/PullToRefresh 它的工作事件,如果列表没有项目,我已经在>=1.6安卓手机上测试了它。

欢迎任何建议或改进:)


我还为Android实现了一个健壮的、开源的、易于使用的和高度可定制的PullToRefresh库。你可以用PullToRefreshListView替换你的ListView,就像在项目页面的文档中描述的那样。

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


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

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

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


注意,在Android和WP上实现时,有一些UX问题需要解决。

“为什么设计师/开发者不应该像iOS应用那样执行拉式刷新,一个很好的指标是谷歌及其团队在Android上从未使用过拉式刷新,而他们却在iOS上使用它。”

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


我有很简单的方法来做到这一点,但现在肯定是万无一失的方法 这是我的代码 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;
    }
}

你只需要在你的活动上实现ListViewTouchEventListener,你想使用这个ListView并设置监听器

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

这对我很有用:)


没有人提到新的类型的“拉刷新”,显示在操作栏的顶部,就像谷歌Now或Gmail应用程序。

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


最后,谷歌发布了一个官方版本的拉取刷新库!

它被称为swiperfreshlayout,在支持库中,文档在这里:

Add SwipeRefreshLayout as a parent of view which will be treated as a pull to refresh the layout. (I took ListView as an example, it can be any View like LinearLayout, ScrollView etc.) <androidx.swiperefreshlayout.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pullToRefresh" android:layout_width="match_parent" android:layout_height="match_parent"> <ListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent"/> </androidx.swiperefreshlayout.widget.SwipeRefreshLayout> Add a listener to your class 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); } }); }

你也可以调用pullToRefresh.setRefreshing(true/false);按您的要求。

更新

Android支持库已弃用,并已被AndroidX所取代。新库的链接可以在这里找到。

此外,你需要添加以下依赖到你的项目:

implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'

OR

你可以去Refactor>>Migrate to AndroidX, Android Studio会为你处理依赖项。


我认为最好的库是:https://github.com/chrisbanes/Android-PullToRefresh。

适用于:

ListView
ExpandableListView
GridView
WebView
ScrollView
HorizontalScrollView
ViewPager

要获得最新的棒棒糖拉刷新:

下载最新的棒棒糖SDK和Extras/Android支持库 将项目的构建目标设置为Android 5.0(否则支持包可能会与资源有错误) 更新libs/android-support-v4.jar到21版 使用android.support.v4.widget。swiperfreshlayout + android.support.v4.widget. swiperfreshlayout . onrefreshlistener

详细的指南可以在这里找到:http://antonioleiva.com/swiperefreshlayout/

加上ListView,我建议阅读评论中的canChildScrollUp();)


Yalantis的“拉到刷新”非常有趣。 Gif for iOS,但你可以检查它:)

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


要实现android的拉到刷新,试试这段代码,

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

 }

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

我假设您使用的是回收视图而不是列表视图。然而,listview仍然可以工作,所以你只需要用listview替换recyclerview并更新java代码中的引用(Fragment)。

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

   }
}

希望这对大众有所帮助


我们首先应该知道什么是拖动刷新布局在android。我们可以在android中调用滑动刷新来刷新。当你从上到下滑动屏幕时,它会基于setOnRefreshListener做一些动作。

这是一个演示如何实现android拉刷新的教程。我希望这能有所帮助。


那些正在寻找实现拉刷新功能的RecyclerView可以遵循我的简单教程如何实现拉刷新的RecyclerView在Android。

要导入的库

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

XML代码

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

活动JAVA代码

import androidx.appcompat.app.AppCompatActivity;
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout;
import android.os.Bundle;
import android.os.Handler;

public class MainActivity extends AppCompatActivity {

private SwipeRefreshLayout swipeRefreshLayout;

...

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
       
        ...
        swipeRefreshLayout = findViewById(R.id.swipe_layout);
        initializeRefreshListener();
}

    void initializeRefreshListener() {

        swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
            @Override
            public void onRefresh() {
                // This method gets called when user pull for refresh,
                // You can make your API call here,
                // We are using adding a delay for the moment
                final Handler handler = new Handler();
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        if(swipeRefreshLayout.isRefreshing()) {
                            swipeRefreshLayout.setRefreshing(false);
                        }
                    }
                }, 3000);
            }
        });
    }

将此添加到布局中

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

现在只需在代码中添加以下这些行

 mSwipeRefreshLayout.setOnRefreshListener(() -> {

       // your refresh code here

    });

都做完了


如果你想在webview或其他地方使用pull来刷新,然后简单地复制粘贴这段代码到你的项目中,它工作得很好。

XML源代码:

   <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/swiperefresh"
        android:layout_width="match_parent"
        android:layout_height="match_parent">
    <WebView
        android:id="@+id/WebView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true">
    </WebView>
    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>

JAVA代码:

  final SwipeRefreshLayout pullToRefresh = findViewById(R.id.swiperefresh);
    pullToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
        @Override
        public void onRefresh()
        {
          Toast.makeText(WebBrowser.this,"pull to refresh",Toast.LENGTH_LONG).show();
            mwebView.loadUrl(mainUrl);
            pullToRefresh.setRefreshing(false);//if false then refresh progress dialog will disappear when page loading finish, but if it is true then always the refresh load dialog show even after the page load or not
        }
    });

构建。Gradle源代码:

 implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0'