忙了两周,楼里 app 终于完成了,25号正式上线,顺便吐槽一下接私活果然好坑,特别是这种工期比较着急的,不过今天款项下来了,拿到 money 之后感觉整个人萌萌哒~~ 废话不多说,今天分享一下自己在工作中对 Android-PullToRefresh的封装
简介
目前 Android 上实现下拉刷新的方式主要有两种:
- 通过修改 HeaderView 的 Padding 实现,常见作法是使用自定义组件继承 ListView,一个类就可以搞定
- 在 istview 底部套一层 ScrollView 或者 LinearLayout,通过移动 ListView 来实现
第一种方法简单但是碰到复杂的 ListView,特别是带有图片的的item就会特别卡,因为主线程刷新界面也需要时间,而改变之后的效果只有刷新之后才能看到,所以给人的感觉是一顿一顿的。第二种方法就不会出现这样的效果,这里推荐的是 Android-PullToRefresh,具体使用大家可以看该项目的 demo,该项目对常见的带滑动的组件都有支持,很强大,而且可以定制。
使用
我的封装主要是对消息处理的封装和页码计算的封装,使你只用写自己逻辑而不用管这些细节
直接看代码, 首先是封装类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
| package com.louli.activity.louli;
import java.text.SimpleDateFormat; import java.util.List; import android.app.Activity; import android.os.Message; import android.widget.BaseAdapter; import android.widget.ListView; import android.widget.Toast;
import com.handmark.pulltorefresh.library.PullToRefreshBase; import com.handmark.pulltorefresh.library.PullToRefreshBase.Mode; import com.handmark.pulltorefresh.library.PullToRefreshBase.OnRefreshListener2; import com.handmark.pulltorefresh.library.PullToRefreshListView; import com.louli.community.R;
public abstract class ListViewBaseActivity extends Activity {
public int pageCount = 1;
public int status;
public int getPageCount() { return pageCount; }
public void setPageCount(int pageCount) { this.pageCount = pageCount; }
public abstract List<?> getList();
public abstract PullToRefreshListView getListView();
public abstract BaseAdapter getAdapter();
public abstract void loadData();
protected PullToRefreshListView initListView(int id) { PullToRefreshListView listView = (PullToRefreshListView) findViewById(id); if (listView == null) { return null; } return initListView(listView); }
protected PullToRefreshListView initListView(PullToRefreshListView listView) { if (listView == null) { return null; } listView.setMode(Mode.BOTH); listView.getLoadingLayoutProxy(false, true).setPullLabel(getResources().getString(R.string.push_label)); listView.getLoadingLayoutProxy(false, true).setRefreshingLabel(getResources().getString(R.string.refreshing_label)); listView.getLoadingLayoutProxy(false, true).setReleaseLabel(getResources().getString(R.string.release_label)); listView.getLoadingLayoutProxy(true, false).setPullLabel(getResources().getString(R.string.pull_label)); listView.getLoadingLayoutProxy(true, false).setRefreshingLabel(getResources().getString(R.string.refreshing_label)); listView.getLoadingLayoutProxy(true, false).setReleaseLabel(getResources().getString(R.string.release_label));
listView.setOnRefreshListener(new OnRefreshListener2Impl()); return listView; }
@SuppressWarnings({ "unchecked", "rawtypes" }) protected void loadSucess(Message msg) { List ls = (List) msg.obj; if (getPageCount() == 1) { getList().clear(); getListView().setMode(Mode.BOTH); } if (ls != null) { getList().addAll(ls); } getAdapter().notifyDataSetChanged(); getListView().onRefreshComplete(); };
protected void loadZeroDate(Message msg) { if (getPageCount() == 1) { Toast.makeText(this, R.string.zero_date, Toast.LENGTH_SHORT).show();
} else { Toast.makeText(this, R.string.msg_last, Toast.LENGTH_SHORT).show(); } getAdapter().notifyDataSetChanged(); getListView().onRefreshComplete(); getListView().setMode(Mode.PULL_FROM_START); };
protected void loadFalt(Message msg) { Toast.makeText(this, R.string.load_error, Toast.LENGTH_SHORT).show(); getAdapter().notifyDataSetChanged(); getListView().onRefreshComplete(); };
private class OnRefreshListener2Impl implements OnRefreshListener2<ListView> { SimpleDateFormat sdf = new SimpleDateFormat(getResources().getString(R.string.refresh_for) + ":MM-dd hh:mm");
@Override public void onPullDownToRefresh(PullToRefreshBase<ListView> refreshView) { status = 1; setPageCount(1); loadData(); String label = sdf.format(System.currentTimeMillis()); refreshView.getLoadingLayoutProxy().setLastUpdatedLabel(label); }
@Override public void onPullUpToRefresh(PullToRefreshBase<ListView> refreshView) { status = -1; setPageCount(getPageCount() + 1); loadData(); String label = sdf.format(System.currentTimeMillis()); refreshView.getLoadingLayoutProxy().setLastUpdatedLabel(label); } }
}
|
如果你的界面里有一个以上的 PullToRefreshListView 组件,那你需要额外重写 getPageCount 和 setPageCount 来自己控制页码,当然这个时候其他几个重写的方法也需要你加上判断,具体示例我会在文章最后附上
下面看例子代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142
| package com.test;
import android.os.Message;
public class ChannelExhibitionListActivity extends ListViewBaseActivity {
PullToRefreshListView _listView; List<ChannelExhibitionListItem> _list; ChannelExhibitionListAdapter _adapter;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.channel_exhibition_list_activity); init(); }
private void init() { _listView = initListView(R.id.listView); ListView actualListView = _listView.getRefreshableView(); _adapter = new ChannelExhibitionListAdapter(this); _list = new ArrayList<ChannelExhibitionListItem>(); _adapter.setList(_list); actualListView.setOnItemClickListener(new OnItemClickListener() {
@Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { position--; } }); actualListView.setAdapter(_adapter);
}
Handler _handler = new Handler() { public void handleMessage(android.os.Message msg) { switch (msg.what) { case LOAD_SUCCESS: loadSucess(msg); break; case LOAD_FAIL: loadFalt(msg); break; case LOAD_NODATA: loadZeroDate(msg); break; } } };
Thread loadThread;
@Override public void loadData() { createCountryThread(); loadThread.start(); }
private void createCountryThread() { loadThread = new Thread(new Runnable() {
@Override public void run() { List<ChannelExhibitionListItem> channels = new ArrayList<ChannelExhibitionListItem>(); try { StringBuffer loadService = new StringBuffer(); loadService.append("?r=findlist&pagesize=15&pagenow=" + getPageCount());
String res = HttpConstants.getPHPRequest("url", loadService.toString()); if (res == null || res.equals("")) { throw new Exception("resoult=" + res); } JSONObject resultJsonObject = new JSONObject(res); int code = resultJsonObject.getInt("returncode"); if (code == 0) { JSONArray datas = resultJsonObject.getJSONArray("result"); if (datas.length() == 0) { Message m = _handler.obtainMessage(LOAD_NODATA); _handler.sendMessage(m); return; } int size = datas.length(); for (int i = 0; i < size; i++) { JSONObject obj = (JSONObject) datas.get(i); ChannelExhibitionListItem item = new ChannelExhibitionListItem(); item.setId("");
channels.add(item); } Message message = _handler.obtainMessage(LOAD_SUCCESS); message.obj = channels; _handler.sendMessage(message); return; }else if(code == 1){ Message m = _handler.obtainMessage(LOAD_NODATA); _handler.sendMessage(m); return; } Message m = _handler.obtainMessage(LOAD_FAIL); _handler.sendMessage(m); } catch (Exception e) { Message m = _handler.obtainMessage(LOAD_FAIL); _handler.sendMessage(m); } finally { } } }); }
@Override public List<?> getList() { return _list; }
@Override public PullToRefreshListView getListView() { return _listView; }
@Override public BaseAdapter getAdapter() { return _adapter; } }
|
以上代码只是逻辑代码,复制在自己的项目中是不能运行的,参考着就可以写了,因为我们的项目是使用的 httpClient+Handler 回调,所以用这个特别方便, 如果你们项目使用 Volley 那就更简单了,稍微修改一下就能用。
最后是布局 布局只需要把 ListView 替换实现就可以 其他的一下属性和 ListView 通用。
1 2 3 4 5 6 7 8 9 10 11 12 13
| <com.handmark.pulltorefresh.library.PullToRefreshListView android:id="@+id/listView" android:layout_width="match_parent" android:layout_height="match_parent" android:cacheColorHint="#00000000" android:divider="#19000000" android:dividerHeight="1dp" android:fadingEdge="none" android:fastScrollEnabled="false" android:footerDividersEnabled="true" android:headerDividersEnabled="true" android:smoothScrollbar="true" > </com.handmark.pulltorefresh.library.PullToRefreshListView>
|
附
多个 PullToRefreshListView 组件时的示例代码 , 其他几个重写的方法也要这样修改
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
|
int num=1;
private int count_p = 1; private int count_r = 1;
public int getPageCount() { if (num ==1) { return count_p; }else{ return count_r; } }
public void setPageCount(int pageCount) { if (num ==1) { this.count_p = pageCount; }else{ this.count_r = pageCount; } }
|
写完啦,我要去腐败喽。