PullToRefresh(下拉刷新)源码浅析
来源:互联网 发布:零基础网络运维工程师 编辑:程序博客网 时间:2024/05/22 00:40
提要:本文主要介绍了android提供的原生下拉刷新控件SwipeRefreshLayout;在github上,由作者Chris Banes实现的第三方下拉刷新(上拉刷新)控件的源码浅析以及根据其源码自己实现的简单下拉刷新demo。
系统控件SwipeRefreshLayout浅析
下拉刷新(上拉刷新)是近两三年android APP比较流行的实现页面更新的控件,可以使用android.support.v4.widget包的原生控件SwipeRefreshLayout实现下拉刷新功能,本demo实现了每次执行下拉刷新后生成一个1-100之间的随机整数,效果如下:
向下拉动
正在刷新
刷新完毕
xml布局文件
<android.support.v4.widget.SwipeRefreshLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:id="@+id/swipe_refresh" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <ScrollView android:layout_width="match_parent" android:layout_height="match_parent" android:text="@string/hello_world" > <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" > <TextView android:id="@+id/text_view" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下拉刷新以生成一个随机数:" android:textSize="23sp" /> <TextView android:id="@+id/text_view_generate" android:layout_width="wrap_content" android:layout_height="wrap_content" android:textColor="#69FF0000" android:textSize="25sp" /> </LinearLayout> </ScrollView></android.support.v4.widget.SwipeRefreshLayout>
xml布局代码如上所示,在引入SwipeRefreshLayout控件时,需要写全限定类名;另外需要注意的是,该控件只能嵌套一个直接子控件,而且这个子控件必须是具有滑动功能的AdapterView(如ListView,Spinner,GridView等)。
activity业务逻辑
public class MainActivity extends Activity { private SwipeRefreshLayout mSwipeRefreshLayout; private TextView mTextView; private Handler mHandler; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mTextView = (TextView) findViewById(R.id.text_view_generate); mHandler = new Handler(); mSwipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refresh); mSwipeRefreshLayout.setOnRefreshListener(new OnRefreshListener() { @Override public void onRefresh() { // TODO Auto-generated method stub // 产生一个刷新效果的动画 mSwipeRefreshLayout.setRefreshing(true); mHandler.postDelayed(new Runnable() { @Override public void run() { // TODO Auto-generated method stub // 三秒后停止刷新动画 mSwipeRefreshLayout.setRefreshing(false); // 产生1-100随机整数 int i = (int) (Math.random() * 100 + 1); mTextView.setText(String.valueOf(i)); } }, 3000); } }); }}
activity代码如上所示,首先声明SwipeRefreshLayout控件并绑定setOnRefreshListener监听器,参数是一个OnRefreshListener类型的接口对象,需要实现接口中未实现的方法onRefresh,在该方法中首先调用SwipeRefreshLayout的方法setRefreshing(true)方法,表示开启动画效果,接着在Handler的postDelay方法中传入两个参数,第一个参数是一个匿名Runnable接口对象,第二个参数是一个int类型整数,本demo中传入3000,代表3秒,该方法表示动画显示的持续时长,然后在run方法中关闭动画效果,并进行相应的UI操作。
系统自带的原生下拉刷新控件SwipeRefreshLayout的优点是比较简洁,没有过多花哨的动画效果,android版chrome浏览器的下拉刷新功能便使用的该控件(chrome是我最喜欢的android浏览器),然而缺点也显而易见,那就是扩展性不够好,对于现今这个APP也看脸的时代,没有炫酷的动画已经很难满足用户的需要,另外,该控件不支持上拉刷新,如果打算实现上拉刷新和更多动画效果,需要下面介绍的第三方控件。
第三方控件PullToRefresh介绍
PullToRefresh是一个开源控件,不仅支持下拉刷新,还支持上拉刷新,而且可以利用刷新时的动画效果为用户提供有用信息(如刷新时间,手势操作提示等),很多商业级别的应用已经才用了这个控件,该控件有以下特点:
- 支持上拉刷新、下拉刷新或同时支持上拉刷新和下拉刷新;
- 支持所有设备的动画滑动;
- Android2.3版本以上支持整屏下拉(上拉);
- 支持下列控件作为直接子控件
-ListView
-ExpandableListView
-GridView
-WebView
-ScrollView
-HorizontalScrollView
-ViewPager - 当滑到底部时可以弹出信息提示;
- 支持Maven;
- 当某个页面具有下拉刷新(上拉刷新)的功能时,给提示用户;
- 许多自定义属性;
- 支持ListFragment。
该控件的demo源程序可以在github上下载,地址是:https://github.com/chrisbanes/Android-PullToRefresh。下面将浅析其中的部分代码。
PullToRefresh效果
先看看该控件包含一个ListView的效果:
向下拉动,显示”放开以刷新”的提示和上次刷新的时间,左边显式圆形箭头图标
松手后,显示”正在载入…”,左侧的圆形箭头按钮不断转动
刷新完毕后,ListView在第一行增加一条内容”Added after refresh…”
当滑到底部时,Toast出”End of List!”
PullToRefresh的xml布局
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" ><!-- The PullToRefreshListView replaces a standard ListView widget. --> <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" /></LinearLayout>
xml布局控件做了封装,控件com.handmark.pulltorefresh.library.PullToRefreshListView里面含有一个ListView。
PullToRefresh的activity
public final class PullToRefreshListActivity extends ListActivity { static final int MENU_MANUAL_REFRESH = 0; static final int MENU_DISABLE_SCROLL = 1; static final int MENU_SET_MODE = 2; static final int MENU_DEMO = 3; private LinkedList<String> mListItems; private PullToRefreshListView mPullRefreshListView; private ArrayAdapter<String> mAdapter; /** Called when the activity is first created. */ @Override 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); 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); } } private String[] mStrings = { "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi", "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre", "Allgauer Emmentaler", "Abbaye de Belloc", "Abbaye du Mont des Cats", "Abertam", "Abondance", "Ackawi", "Acorn", "Adelost", "Affidelice au Chablis", "Afuega'l Pitu", "Airag", "Airedale", "Aisy Cendre", "Allgauer Emmentaler" };}
首先为PullToRefresh控件绑定监听器setOnRefreshListener,参数是匿名接口OnRefreshListener对象,注意,若希望同时实现上拉刷新和下拉刷新,需实现匿名接口OnRefreshListener2;在onRefresh方法中首先设置了显示刷新的时间,然后执行异步任务AsyncTask,在onPostExecute方法中为ListView增加一行,并通知Adapter刷新页面,最后调用onRefreshComplete方法完成刷新;绑定setOnLastItemVisibleListener监听器用于监听ListView滑到底部时的情况。
利用PullToRefresh实现自定义demo
利用PullToRefresh控件,实现了每次下拉刷新(或上拉刷新)后,生成一组双色球号码的demo。
效果如下所示:
向下拉动,显示文字提示”放开以刷新” 左侧有Android机器人图标转动
松开手,显示”正在载入…”,左侧Android机器人图标转动
刷新完成,生成一组双色球随机号码
向上拉动,底部提示”放开以刷新”,左侧Android机器人图标转动
松开手,显示”正在载入…”,左侧Android机器人图标转动
刷新完成,生成第二组双色球随机号码
xml布局
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="${relativePackage}.${activityClass}" > <com.handmark.pulltorefresh.library.PullToRefreshListView xmlns:ptr="http://schemas.android.com/apk/res-auto" 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" ptr:ptrMode="both" ptr:ptrDrawable="@drawable/ic_launcher" /></RelativeLayout>
注意要引用控件的全限定类名com.handmark.pulltorefresh.library.PullToRefreshListView。
activity业务逻辑
public class MainActivity extends Activity { private PullToRefreshListView mPullToRefresh; private ArrayAdapter<String> mArrayAdapter; private List<String> mList; private ListView mListView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mList = new ArrayList<String>(); mArrayAdapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, mList); mPullToRefresh = (PullToRefreshListView) findViewById(R.id.pull_refresh_list); mListView = mPullToRefresh.getRefreshableView(); mListView.setAdapter(mArrayAdapter); // 同时实现上拉刷新和下拉刷新 mPullToRefresh.setOnRefreshListener(new OnRefreshListener2() { // 实现下拉刷新 @Override public void onPullDownToRefresh(PullToRefreshBase refreshView) { // TODO Auto-generated method stub new GetDataTask().execute(); } // 实现下拉刷新 @Override public void onPullUpToRefresh(PullToRefreshBase refreshView) { // TODO Auto-generated method stub new GetDataTask().execute(); } }); } private class GetDataTask extends AsyncTask<Void, Void, String> { @Override protected String doInBackground(Void... params) { // Simulates a background job. try { Thread.sleep(2000); } catch (InterruptedException e) { } return generateData(); } @Override protected void onPostExecute(String result) { mList.add(result); mArrayAdapter.notifyDataSetChanged(); // Call onRefreshComplete when the list has been refreshed. mPullToRefresh.onRefreshComplete(); super.onPostExecute(result); } // 生成ListView中的一行数据 private String generateData() { Set<String> treeSet = new TreeSet<String>(); do { treeSet.add(generateARedBall()); } while (treeSet.size() <= 6); String[] _string = new String[6]; _string = treeSet.toArray(_string); StringBuilder _stringBuilder = new StringBuilder(); _stringBuilder.append("【第" + (mList.size() + 1) + "组】红:"); for (int _i = 0; _i < 6; _i++) { _stringBuilder.append(_string[_i]); _stringBuilder.append(", "); } _stringBuilder = _stringBuilder.delete(_stringBuilder.length() - 2, _stringBuilder.length() - 1); _stringBuilder.append("蓝:" + generateABlueBall()); return _stringBuilder.toString(); } // 生成一组红色球号码 private String generateARedBall() { // TODO Auto-generated method stub int i = (int) (Math.random() * 99 + 1); if (i < 10) { return "0" + String.valueOf(i); } else { return String.valueOf(i); } } // 生成一个蓝色球号码 private String generateABlueBall() { // TODO Auto-generated method stub int i = (int) (Math.random() * 16 + 1); if (i < 10) { return "0" + String.valueOf(i); } else { return String.valueOf(i); } } }}
代码实现了上述图片所示效果,该程序通过匿名接口OnRefreshListener2对象实现了上拉刷新和下拉刷新两种手势操作,生成双色球随机数。
- PullToRefresh(下拉刷新)源码浅析
- PullToRefresh(下拉刷新)源码浅析
- 开源Android-PullToRefresh下拉刷新源码分析
- 开源Android-PullToRefresh下拉刷新源码分析
- 基于pulltorefresh源码修改下拉刷新动画
- 开源Android-PullToRefresh下拉刷新源码分析
- Android下拉刷新PullToRefresh源码解读
- android pulltorefresh 下拉刷新
- PullToRefresh 下拉刷新菜单
- PullToRefresh下拉刷新
- PullToRefresh下拉刷新框架
- PullToRefresh的下拉刷新
- 5.3.2 开源Android-PullToRefresh下拉刷新源码分析
- PullToRefresh框架源码分析(Ⅱ)下拉刷新的过程分析
- Android下拉刷新控件SwipeRefreshLayout源码浅析
- Android下拉刷新控件SwipeRefreshLayout源码浅析
- Android下拉刷新控件SwipeRefreshLayout源码浅析
- android控件 下拉刷新pulltorefresh
- DataStructures:Introduction
- C# 事务高效率插入数据
- 简易在线投票系统(php)——投票结果页面
- 秀发润泽一冬,护发首当其冲
- 关于spring mvc拦截器拦截js文件等导致无法正常使用问题的解决
- PullToRefresh(下拉刷新)源码浅析
- log4j的简单介绍和应用以及与commons-logging的区别
- JMS教程(一)
- HTTPUrlConnection 出现 FileNotFoundException 的问题
- Java中static作用详解
- Java验证是否是身份证号
- js Math 对象方法
- abap报表中(ALV或者普通屏幕的定制控制中)如何让列可以使用求和按钮
- QT环境下出现undefined refence to symbol...