Android-PullToRefresh 是一个github上的开源下拉刷新类库, GitHub 。此外,该作者还有另外一个实用度和关注量极高的项目–另一种Android ActionBar的实现:GitHub 。
下载后的配置:
引用项目:
参考:http://my.oschina.net/cuitongliang/blog/170737
解压。在Android-PullToRefresh-master文件夹下,我们会看到还有三个文件夹:extras,
library,sample。其中sample就是作者为我们提供的Demo,library是我们在使用Sample必须用到的jar。extras中是使用ListFragment和ViewPage用到的jar。
将sample,library,ListFragment和ViewPage导入。
library是一个类库
PullToRefreshListFragment和PullToRefreshViewPager也是一个类库,同时引用了library。
sample工程引用三个类库:
注意:尝试将类库导出jar然后放到工程中引用,报错。
demo里面提供了各种例子,其中PullToRefreshListActivity是listview的下拉刷新:
1、布局文件
将普通的 listview 替换为 <com.handmark.pulltorefresh.library.PullToRefreshListView
<com.handmark.pulltorefresh.library.PullToRefreshListView android:id="@+id/pull_refresh_list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:cacheColorHint="#00000000" android:divider="#19000000" android:dividerHeight="4dp" android:fadingEdge="none" android:fastScrollEnabled="false" android:footerDividersEnabled="false" android:headerDividersEnabled="false" android:smoothScrollbar="true" />
2、代码
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_ptr_list); mPullRefreshListView = (PullToRefreshListView) findViewById(R.id.pull_refresh_list); // Set a listener to be invoked when the list should be refreshed. mPullRefreshListView.setOnRefreshListener(new OnRefreshListener<ListView>() { @Override public void onRefresh(PullToRefreshBase<ListView> refreshView) { String label = DateUtils.formatDateTime(getApplicationContext(), System.currentTimeMillis(), DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_ABBREV_ALL); // Update the LastUpdatedLabel refreshView.getLoadingLayoutProxy().setLastUpdatedLabel(label); // Do work to refresh the list here. new GetDataTask().execute(); } }); // Add an end-of-list listener mPullRefreshListView.setOnLastItemVisibleListener(new OnLastItemVisibleListener() { @Override public void onLastItemVisible() { Toast.makeText(PullToRefreshListActivity.this, "End of List!", Toast.LENGTH_SHORT).show(); } }); ListView actualListView = mPullRefreshListView.getRefreshableView(); // Need to use the Actual ListView when registering for Context Menu registerForContextMenu(actualListView); mListItems = new LinkedList<String>(); mListItems.addAll(Arrays.asList(mStrings)); mAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mListItems); /** * Add Sound Event Listener */ SoundPullEventListener<ListView> soundListener = new SoundPullEventListener<ListView>(this); soundListener.addSoundEvent(State.PULL_TO_REFRESH, R.raw.pull_event); soundListener.addSoundEvent(State.RESET, R.raw.reset_sound); soundListener.addSoundEvent(State.REFRESHING, R.raw.refreshing_sound); mPullRefreshListView.setOnPullEventListener(soundListener); // You can also just use setListAdapter(mAdapter) or // mPullRefreshListView.setAdapter(mAdapter) actualListView.setAdapter(mAdapter); } private class GetDataTask extends AsyncTask<Void, Void, String[]> { @Override protected String[] doInBackground(Void... params) { // Simulates a background job. try { Thread.sleep(4000); } catch (InterruptedException e) { } return mStrings; } @Override protected void onPostExecute(String[] result) { mListItems.addFirst("Added after refresh..."); mAdapter.notifyDataSetChanged(); // Call onRefreshComplete when the list has been refreshed. mPullRefreshListView.onRefreshComplete(); super.onPostExecute(result); } }
mPullRefreshListView 实现监听 setOnRefreshListener 实现下拉刷新 ,setOnLastItemVisibleListener 实现列表底部监听,actualListView 是实际的listview基本上可以像普通listview使用,但是在项目中尝试使用actualListView.setOnScrollListener时,导致setOnLastItemVisibleListener 不起作用了,应该是监听冲突了。所以使用时要特别注意。既然用了mPullRefreshListView 就尽量使用它提供的各种监听和方法。
3、支持下拉刷新:
参考:http://rensanning.iteye.com/blog/2004812
设置Mode
PullToRefreshListView mListView = (PullToRefreshListView) findViewById(R.id.list_view);
mListView.setMode(Mode.BOTH);
- Mode.BOTH:同时支持上拉下拉
- Mode.PULL_FROM_START:只支持下拉Pulling Down
- Mode.PULL_FROM_END:只支持上拉Pulling Up
如果Mode设置成Mode.BOTH,需要设置刷新Listener为OnRefreshListener2,并实现onPullDownToRefresh()、onPullUpToRefresh()两个方法。
如果Mode设置成Mode.PULL_FROM_START或Mode.PULL_FROM_END,需要设置刷新Listener为OnRefreshListener,同时实现onRefresh()方法。当然也可以设置为OnRefreshListener2,但是Mode.PULL_FROM_START的时候只调用onPullDownToRefresh()方法,Mode.PULL_FROM的时候只调用onPullUpToRefresh()方法.
mPullRefreshListView.setMode(Mode.BOTH); // Set a listener to be invoked when the list should be refreshed. mPullRefreshListView .setOnRefreshListener(new OnRefreshListener2<ListView>() { @Override public void onPullUpToRefresh( PullToRefreshBase<ListView> refreshView) { …… } @Override public void onPullDownToRefresh( PullToRefreshBase<ListView> refreshView) { …… } });
4、个性化配置
参考:
http://blog.csdn.net/wwhh393/article/details/9722199
http://www.apkbus.com/android-116565-1-1.html
使用xml
可以调整ptrMode,字体颜色等
<com.handmark.pulltorefresh.library.PullToRefreshListView xmlns:ptr="http://schemas.android.com/apk/res-auto" android:id="@+id/my_list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:cacheColorHint="#00000000" android:fadingEdge="none" android:fastScrollEnabled="false" android:footerDividersEnabled="false" android:headerDividersEnabled="false" android:smoothScrollbar="true" ptr:ptrMode="pullUpFromBottom" ptr:ptrHeaderTextColor="@color/silver_gray" ptr:ptrHeaderSubTextColor="@color/orange" ptr:ptrDrawable="@drawable/share_to_time_line_icon" ptr:ptrAnimationStyle="flip" ptr:ptrHeaderTextAppearance="@android:attr/textAppearanceMedium"/>
属性说明
ptr:AnimationStyle : flip 这个效果是有向下和向上的两个箭头的,rotate 没有箭头不管怎么拉都是一个 progress bar
ptr:Mode :both 指的是 listview 的上面和下面都有这种拉动刷新的效果,下面的刷新通常我们在滑到最下面然后 loading 数据的时候可以看到
ptr:ptrAnimationStyle | 动画效果 提供了两个值 flip和rotate 默认为rotate |
ptr:ptrRefreshableViewBackground | 设置刷新View的背景颜色 |
ptr:ptrHeaderBackground | 设置头部View的背景颜色 |
ptr:ptrHeaderTextColor | 设置头部View文字的颜色 |
ptr:ptrHeaderSubTextColor | 设置头部view副标题文字的颜色 |
ptr:ptrMode |
pullFromStart: pullFromEnd: both; |
其他的属性可以在 /library/res/values/attrs.xml下面查看。
参考的文章提到几个注意点,没有实践,贴出来记录先:
此处有几个地方要注意:
1. 如果想对 list item 点击之后做一些事情,此处有个问题要注意下,那就是我们的下来显示的 view 是 header view,所以此处在 onItemClick() 函数中传入的 position 不是从 0 开始而是从 1 开始,如果我们使用通常情况下的 mAdapter 去 getItem() 则实际中始终获取的都是我们点击 item 的下一个 item 的位置,所以此处我们要通过传进来的 parent 的 adapter 来获取 item,详细可以参考当ListView有Header时,onItemClick里的position不正确
2. 因为下拉的时候显示的文字,每个人有每个的需求,所以会不一样,所以就需要使用 setOnPullEventListener() 来更新文字,这个开源库自己提供的 sample 中更新文字是放到 setOnRefreshListener() 中,但是那个只是在刷新的时候才更新问题,通过对比那些常用 app 的下拉效果你会发现那个时候在更新已经慢了,所以要放到这里
3. 此处代码没有列出来,就是 refresh 完了之后要把 pull view hide 起来,调用 onRefreshComplete() 即可,详情可以参考它自己提供的 sample。
4. 还要注意的是,还有很大的需求是点击刷新,那么点击之后这个 pull view 也要 show 出来,但是不应该 show "下拉可以刷新" 和 "松开可以刷新" 这两个画面,而是直接显示正在刷新的那个画面,这要怎么做到的呢?通过setRefreshing()这个函数即可做到,对应有另外一个函数叫做demo() 它包括了 “下拉->松开->刷新” 的整个过程,这是我们在这种条件下不需要的。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical"> <com.handmark.pulltorefresh.library.PullToRefreshListView xmlns:ptr="http://schemas.android.com/apk/res-auto" android:id="@+id/my_list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:cacheColorHint="#00000000" android:fadingEdge="none" android:fastScrollEnabled="false" android:footerDividersEnabled="false" android:headerDividersEnabled="false" android:smoothScrollbar="true" ptr:ptrAnimationStyle="flip" ptr:ptrHeaderTextAppearance="@android:attr/textAppearanceMedium"/> <!-- Here is the view to show if the list is emtpy --> <ScrollView android:id="@+id/empty" android:layout_width="fill_parent" android:layout_height="fill_parent" android:fillViewport="true"> <LinearLayout android:layout_width="fill_parent" android:layout_height="wrap_content" android:orientation="vertical"> <TextView android:id="@+id/emptyText" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text="@string/noText" android:textSize="20sp" android:textColor="?android:attr/textColorSecondary" android:paddingLeft="10dip" android:paddingRight="10dip" android:paddingTop="10dip" android:lineSpacingMultiplier="0.92" android:gravity="center" /> </LinearLayout> </ScrollView> </LinearLayout>
在这个 layout 中分为上下两个部分,上面是一个 listview, 下面是一个 empty view,用来在没有内容的时候显示,通过 listview 的 setEmptyView()就可以达到这个效果,千万不要自己费事去写两个 view 的逻辑控制代码。