1.添加加载更多布局
1_初始化和隐藏代码
在RefreshListView构造方法中调用
class="brush:java;gutter:true;">private void initFooterView(Context context) { View footerView = View.inflate(context, R.layout.refresh_listview_footer, null); //隐藏代码 footerView.measure(0, 0); int footerViewHeight = footerView.getMeasuredHeight(); footerView.setPadding(0, -footerViewHeight, 0, 0); this.addFooterView(footerView); }
2_布局文件refresh_listview_footer.xml
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 3 android:layout_width="match_parent" 4 android:layout_height="wrap_content" 5 android:gravity="center" 6 android:orientation="horizontal" > 7 8 <ProgressBar 9 android:layout_margin="5dip" 10 android:layout_width="wrap_content" 11 android:layout_height="wrap_content" 12 android:indeterminateDrawable="@drawable/custom_progressbar" /> 13 14 <TextView 15 android:layout_marginLeft="10dip" 16 android:layout_width="wrap_content" 17 android:layout_height="wrap_content" 18 android:text="加载更多中..." 19 android:textColor="#ff0000" 20 android:textSize="25sp" /> 21 22 </LinearLayout>logs_code_collapse">refresh_listview_footer.xml
2.拖动到底部的时候
1 /** 2 * 菜单页面对应的新闻页签页面 3 * 总共有12个 4 * @author Administrator 5 * 6 */ 7 public class TabMenuDetailPager extends MenuDetailBasePagerimplements OnPageChangeListener { 8 /** 9 * 新闻中心-新闻菜单对应的标签对应的数据 10 */ 11 private NewCenterTag newCenterTag; 12 ....................... 13 /** 14 * 加载更多数据的URL 15 */ 16 private String moreUrl; 17 /** 18 * 是否加载更多数据中 19 */ 20 protected boolean isLoadingMore = false; 21 ................... 22 @Override 23 public View initView() { 24 View view = View.inflate(mActivity, R.layout.tab_detail, null); 25 //把View注入到XUtils框架中 26 ViewUtils.inject(this, view); 27 28 .......................... 29 30 //设置监听下拉刷新 31 mListView.setOnRefreshListener(new OnRefreshListener() { 32 33 @Override 34 public void onPullDownRefresh() { 35 isPullDownRefreshing = true; 36 getDataFromNet(); 37 38 } 39 @Override 40 public void onLoadingMore() { 41 if(TextUtils.isEmpty(moreUrl)){ 42 Toast.makeText(mActivity, "没有更多数据了", 1).show(); 43 mListView.onRefreshFinish(false); 44 }else{ 45 //有更多数据,要加载更多数据了 46 getMoreDataFromNet(); 47 } 48 } 49 }); 50 51 52 return view; 53 } 54 55 /** 56 * 加载更多数据 57 */ 58 protected void getMoreDataFromNet() { 59 60 HttpUtils httpUtils = new HttpUtils(); 61 httpUtils.send(HttpMethod.GET, moreUrl, new RequestCallBack<String>() { 62 @Override 63 public void onSuccess(ResponseInfo<String> responseInfo) { 64 System.out.println("加载更多数据成功:"+responseInfo.result); 65 mListView.onRefreshFinish(false); 66 isLoadingMore = true; 67 processData(responseInfo.result); 68 } 69 @Override 70 public void onFailure(HttpException error, String msg) { 71 mListView.onRefreshFinish(false); 72 System.out.println("加载更多数据失败:"+ msg); 73 74 } 75 }); 76 77 78 } 79 80 /** 81 * 处理和解析json数据 82 * @param json 83 */ 84 protected void processData(String json) { 85 86 TabDetailBean bean = parserJson(json); 87 88 if(!isLoadingMore){ 89 System.out.println(bean.data.news.get(0).title); 90 topnews = bean.data.topnews; 91 92 //给ViewPager设置适配器 93 TabDetailAdapter adapter = new TabDetailAdapter(); 94 mViewPager.setAdapter(adapter); 95 96 97 // 把所有的View清除 98 ll_point_group.removeAllViews(); 99 for(int i=0;i<topnews.size();i++){ 100 View point = new View(mActivity); 101 LayoutParams params = new LayoutParams(5, 5) ; 102 point.setBackgroundResource(R.drawable.tab_detail_point_bg); 103 if(i!=0){ 104 params.leftMargin = 10; 105 } 106 point.setEnabled(false); 107 point.setLayoutParams(params); 108 109 ll_point_group.addView(point); 110 } 111 previousPointPosition = 0; 112 //设置默认的图片描述和指示点 113 mtv_title_description.setText(topnews.get(previousPointPosition).title); 114 115 ll_point_group.getChildAt(previousPointPosition).setEnabled(true); 116 117 118 119 //设置页面改变的监听 120 mViewPager.setOnPageChangeListener(this); 121 122 //设置适配器和对应的数据 123 newsLists = bean.data.news; 124 listViewAdapter = new ListViewAdapter(); 125 mListView.setAdapter(listViewAdapter); 126 127 // mListView.addHeaderView(v) ;//把一个视图一头的方式添加到ListView中 128 129 }else{ 130 //把列表新闻取出来,在加载到以前的集合中,在刷新数据 131 isLoadingMore = false; 132 List<News>moreDataNews = bean.data.news; 133 newsLists.addAll(moreDataNews); 134 listViewAdapter.notifyDataSetChanged();//刷新数据 135 136 137 } 138 139 } 140 ................ 141 /** 142 * 用Gson开源项目解析json 143 * @param json 144 */ 145 private TabDetailBean parserJson(String json) { 146 Gson gson = new Gson(); 147 TabDetailBean bean = gson.fromJson(json, TabDetailBean.class); 148 moreUrl = bean.data.more; 149 if(TextUtils.isEmpty(moreUrl)){ 150 moreUrl = null; 151 }else{ 152 moreUrl = ConstantUtils.server_url+moreUrl; 153 } 154 155 return bean; 156 } 157 @Override 158 public void onPageScrollStateChanged(int arg0) { 159 // TODO Auto-generated method stub 160 161 } 162 @Override 163 public void onPageScrolled(int arg0, float arg1, int arg2) { 164 // TODO Auto-generated method stub 165 166 } 167 ............... 168 }TabMenuDetailPager
3.完整代码
1 package com.atguigu.refreshlistview; 2 3 import android.content.Context; 4 import android.util.AttributeSet; 5 import android.view.MotionEvent; 6 import android.view.View; 7 import android.view.animation.Animation; 8 import android.view.animation.RotateAnimation; 9 import android.widget.AbsListView; 10 import android.widget.ImageView; 11 import android.widget.LinearLayout; 12 import android.widget.ListView; 13 import android.widget.ProgressBar; 14 import android.widget.TextView; 15 16 17 import java.text.SimpleDateFormat; 18 import java.util.Date; 19 20 /** 21 * 作用:自定义下拉刷新的ListView 22 */ 23 public class RefreshListview extends ListView { 24 /** 25 * 下拉刷新和顶部轮播图 26 */ 27 private LinearLayout headerView; 28 29 /** 30 * 下拉刷新控件 31 */ 32 private View ll_pull_down_refresh; 33 private ImageView iv_arrow; 34 private ProgressBar pb_status; 35 private TextView tv_status; 36 private TextView tv_time; 37 /** 38 * 下拉刷新控件的高 39 */ 40 private int pullDownRefreshHeight; 41 42 /** 43 * 下拉刷新 44 */ 45 public static final int PULL_DOWN_REFRESH = 0; 46 47 /** 48 * 手松刷新 49 */ 50 public static final int RELEASE_REFRESH = 1; 51 52 53 /** 54 * 正在刷新 55 */ 56 public static final int REFRESHING = 2; 57 58 59 /** 60 * 当前状态 61 */ 62 private int currentStatus = PULL_DOWN_REFRESH; 63 64 private Animation upAnimation; 65 private Animation downAnimation; 66 /** 67 * 加载更多的控件 68 */ 69 private View footerView; 70 /** 71 * 加载更多控件高 72 */ 73 private int footerViewHeight; 74 /** 75 * 是否已经加载更多 76 */ 77 private boolean isLoadMore = false; 78 /** 79 * 顶部轮播图部分 80 */ 81 private View topNewsView; 82 /** 83 * ListView在Y轴上的坐标 84 */ 85 private int listViewOnScreenY = -1; 86 87 88 public RefreshListview(Context context) { 89 this(context, null); 90 } 91 92 public RefreshListview(Context context, AttributeSet attrs) { 93 this(context, attrs, 0); 94 } 95 96 public RefreshListview(Context context, AttributeSet attrs, int defStyleAttr) { 97 super(context, attrs, defStyleAttr); 98 initHeaderView(context); 99 initAnimation(); 100 initFooterView(context); 101 102 } 103 104 private void initFooterView(Context context) { 105 footerView = View.inflate(context, R.layout.refresh_footer, null); 106 footerView.measure(0, 0); 107 footerViewHeight = footerView.getMeasuredHeight(); 108 109 110 footerView.setPadding(0, -footerViewHeight, 0, 0); 111 112 //ListView添加footer 113 addFooterView(footerView); 114 115 116 //监听ListView的滚动 117 setOnScrollListener(new MyOnScrollListener()); 118 } 119 120 /** 121 * 添加顶部轮播图 122 * @param topNewsView 123 */ 124 public void addTopNewsView(View topNewsView) { 125 if(topNewsView != null){ 126 this.topNewsView =topNewsView; 127 headerView.addView(topNewsView); 128 } 129 130 131 } 132 133 class MyOnScrollListener implements OnScrollListener{ 134 135 @Override 136 public void onScrollStateChanged(AbsListView view, int scrollState) { 137 //当静止或者惯性滚动的时候 138 if(scrollState ==OnScrollListener.SCROLL_STATE_IDLE||scrollState ==OnScrollListener.SCROLL_STATE_FLING){ 139 //并且是最后一条可见 140 if(getLastVisiblePosition()>=getCount()-1){ 141 142 //1.显示加载更多布局 143 footerView.setPadding(8,8,8,8); 144 //2.状态改变 145 isLoadMore = true; 146 //3.回调接口 147 if(mOnRefreshListener != null){ 148 mOnRefreshListener.onLoadMore(); 149 } 150 } 151 } 152 153 154 } 155 156 @Override 157 public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) { 158 159 } 160 } 161 162 163 private void initAnimation() { 164 upAnimation = new RotateAnimation(0, -180, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); 165 upAnimation.setDuration(500); 166 upAnimation.setFillAfter(true); 167 168 downAnimation = new RotateAnimation(-180, -360, RotateAnimation.RELATIVE_TO_SELF, 0.5f, RotateAnimation.RELATIVE_TO_SELF, 0.5f); 169 downAnimation.setDuration(500); 170 downAnimation.setFillAfter(true); 171 } 172 173 private void initHeaderView(Context context) { 174 headerView = (LinearLayout) View.inflate(context, R.layout.refresh_header, null); 175 //下拉刷新控件 176 ll_pull_down_refresh = headerView.findViewById(R.id.ll_pull_down_refresh); 177 iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow); 178 pb_status = (ProgressBar) headerView.findViewById(R.id.pb_status); 179 tv_status = (TextView) headerView.findViewById(R.id.tv_status); 180 tv_time = (TextView) headerView.findViewById(R.id.tv_time); 181 182 //测量 183 ll_pull_down_refresh.measure(0, 0); 184 pullDownRefreshHeight = ll_pull_down_refresh.getMeasuredHeight(); 185 186 //默认隐藏下拉刷新控件 187 // View.setPadding(0,-控件高,0,0);//完全隐藏 188 //View.setPadding(0, 0,0,0);//完全显示 189 ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0); 190 191 //添加ListView的头 192 addHeaderView(headerView); 193 } 194 195 private float startY = -1; 196 197 @Override 198 public boolean onTouchEvent(MotionEvent ev) { 199 switch (ev.getAction()) { 200 case MotionEvent.ACTION_DOWN: 201 //1.记录起始坐标 202 startY = ev.getY(); 203 break; 204 case MotionEvent.ACTION_MOVE: 205 if (startY == -1) { 206 startY = ev.getY(); 207 } 208 209 //判断顶部轮播图是否完全显示,只有完全显示才会有下拉刷新 210 211 boolean isDisplayTopNews = isDisplayTopNews(); 212 if(!isDisplayTopNews){ 213 //加载更多 214 break; 215 } 216 217 218 //如果是正在刷新,就不让再刷新了 219 if (currentStatus == REFRESHING) { 220 break; 221 } 222 //2.来到新的坐标 223 float endY = ev.getY(); 224 //3.记录滑动的距离 225 float distanceY = endY - startY; 226 if (distanceY > 0) {//下拉 227 228 //int paddingTop = -控件高 + distanceY; 229 int paddingTop = (int) (-pullDownRefreshHeight + distanceY); 230 231 if (paddingTop < 0 && currentStatus != PULL_DOWN_REFRESH) { 232 //下拉刷新状态 233 currentStatus = PULL_DOWN_REFRESH; 234 //更新状态 235 refreshViewState(); 236 237 } else if (paddingTop > 0 && currentStatus != RELEASE_REFRESH) { 238 //手松刷新状态 239 currentStatus = RELEASE_REFRESH; 240 //更新状态 241 refreshViewState(); 242 243 } 244 245 ll_pull_down_refresh.setPadding(0, paddingTop, 0, 0); 246 //View.setPadding(0,paddingTop,0,0);//动态的显示下拉刷新控件 247 } 248 break; 249 case MotionEvent.ACTION_UP: 250 startY = -1; 251 if (currentStatus == PULL_DOWN_REFRESH) { 252 // View.setPadding(0,-控件高,0,0);//完全隐藏 253 ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0); 254 } else if (currentStatus == RELEASE_REFRESH) { 255 //设置状态为正在刷新 256 currentStatus = REFRESHING; 257 258 refreshViewState(); 259 260 // View.setPadding(0,0,0,0);//完全显示 261 ll_pull_down_refresh.setPadding(0, 0, 0, 0); 262 263 264 //回调接口 265 if (mOnRefreshListener != null) { 266 mOnRefreshListener.onPullDownRefresh(); 267 } 268 } 269 break; 270 271 } 272 return super.onTouchEvent(ev); 273 } 274 275 /** 276 * 判断是否完全显示顶部轮播图 277 * 当ListView在屏幕上的Y轴坐标小于或者等于顶部轮播图在Y轴的坐标的时候,顶部轮播图完全显示 278 * @return 279 */ 280 private boolean isDisplayTopNews() { 281 282 if(topNewsView != null){ 283 //1.得到ListView在屏幕上的坐标 284 int[] location = new int[2]; 285 if(listViewOnScreenY == -1){ 286 getLocationOnScreen(location); 287 listViewOnScreenY = location[1]; 288 } 289 290 //2.得到顶部轮播图在屏幕上的坐标 291 topNewsView.getLocationOnScreen(location); 292 int topNewsViewOnScreenY = location[1]; 293 294 // if(listViewOnScreenY <= topNewsViewOnScreenY){ 295 // return true; 296 // }else{ 297 // return false; 298 // } 299 300 return listViewOnScreenY <= topNewsViewOnScreenY; 301 }else{ 302 return true; 303 } 304 305 } 306 307 private void refreshViewState() { 308 309 switch (currentStatus) { 310 case PULL_DOWN_REFRESH://下拉刷新状态 311 iv_arrow.startAnimation(downAnimation); 312 tv_status.setText("下拉刷新..."); 313 break; 314 315 case RELEASE_REFRESH://手松刷新状态 316 iv_arrow.startAnimation(upAnimation); 317 tv_status.setText("手松刷新..."); 318 break; 319 case REFRESHING://正在刷新状态 320 tv_status.setText("正在刷新..."); 321 pb_status.setVisibility(VISIBLE); 322 iv_arrow.clearAnimation(); 323 iv_arrow.setVisibility(GONE); 324 break; 325 } 326 327 } 328 329 /** 330 * 当联网成功和失败的时候回调该方法 331 * 用户刷新状态的还原 332 * 333 * @param sucess 334 */ 335 public void onRefreshFinish(boolean sucess) { 336 if(isLoadMore){ 337 //加载更多 338 isLoadMore = false; 339 //隐藏加载更多布局 340 footerView.setPadding(0,-footerViewHeight,0,0); 341 }else{ 342 //下拉刷新 343 tv_status.setText("下拉刷新..."); 344 currentStatus = PULL_DOWN_REFRESH; 345 iv_arrow.clearAnimation(); 346 pb_status.setVisibility(GONE); 347 iv_arrow.setVisibility(VISIBLE); 348 //隐藏下拉刷新控件 349 ll_pull_down_refresh.setPadding(0, -pullDownRefreshHeight, 0, 0); 350 if (sucess) { 351 //设置最新更新时间 352 tv_time.setText("上次更新时间:" + getSystemTime()); 353 } 354 } 355 356 357 358 } 359 360 /** 361 * 得到当前Android系统的时间 362 * 363 * @return 364 */ 365 private String getSystemTime() { 366 SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 367 return format.format(new Date()); 368 } 369 370 371 /** 372 * 监听控件的刷新 373 */ 374 public interface OnRefreshListener { 375 376 /** 377 * 当下拉刷新的时候回调这个方法 378 */ 379 public void onPullDownRefresh(); 380 381 /** 382 当加载更多的时候回调这个方法 383 */ 384 public void onLoadMore(); 385 386 } 387 388 private OnRefreshListener mOnRefreshListener; 389 390 391 /** 392 * 设置监听刷新,由外界设置 393 */ 394 public void setOnRefreshListener(OnRefreshListener l) { 395 this.mOnRefreshListener = l; 396 397 } 398 }RefreshListview