1. 程式人生 > >分頁, 上拉重新整理、下拉載入。

分頁, 上拉重新整理、下拉載入。

一、自定義listview

package com.fragment.home;
import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.text.SimpleDateFormat;
import java.util.Date;

import com.example.virtualaccount.R;
public class CustomRefreshListView extends ListView implements OnScrollListener{
	/**
	 * 頭佈局
	 */
	private View headerView;
	/**
	 * 頭部佈局的高度
	 */
	private int headerViewHeight;
	/**
	 * 頭部旋轉的圖片
	 */
	private ImageView iv_arrow;
	/**
	 * 頭部下拉重新整理時狀態的描述
	 */
	private TextView tv_state;
	/**
	 * 下拉重新整理時間的顯示控制元件
	 */
	private TextView tv_time;
	/**
	 * 底部佈局
	 */
	private View footerView;
	/**
	 * 底部旋轉progressbar
	 */
	private ProgressBar pb_rotate;

	/**
	 * 底部佈局的高度
	 */
	private int footerViewHeight;


	/**
	 * 按下時的Y座標
	 */
	private int downY;
	
	private final int PULL_REFRESH = 0;//下拉重新整理的狀態
	private final int RELEASE_REFRESH = 1;//鬆開重新整理的狀態
	private final int REFRESHING = 2;//正在重新整理的狀態

	/**
	 * 當前下拉重新整理處於的狀態
	 */
	private int currentState = PULL_REFRESH;

	/**
	 * 頭部佈局在下拉重新整理改變時,圖示的動畫
	 */
	private RotateAnimation upAnimation,downAnimation;

	/**
	 * 當前是否在載入資料
	 */
	private boolean isLoadingMore = false;

	public CustomRefreshListView(Context context) {
		this(context,null);
	}

	public CustomRefreshListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}
	
	private void init(){
		//設定滑動監聽
		setOnScrollListener(this);
		//初始化頭佈局
		initHeaderView();
		//初始化頭佈局中圖示的旋轉動畫
		initRotateAnimation();
		//初始化為尾佈局
		initFooterView();
	}
	
	/**
	 * 初始化headerView
	 */
	private void initHeaderView() {
		headerView = View.inflate(getContext(), R.layout.head_custom_listview, null);
		iv_arrow = (ImageView) headerView.findViewById(R.id.iv_arrow);
		pb_rotate = (ProgressBar) headerView.findViewById(R.id.pb_rotate);
		tv_state = (TextView) headerView.findViewById(R.id.tv_state);
		tv_time = (TextView) headerView.findViewById(R.id.tv_time);

		//測量headView的高度
		headerView.measure(0, 0);
		//獲取高度,並儲存
		headerViewHeight = headerView.getMeasuredHeight();
		//設定paddingTop = -headerViewHeight;這樣,該控制元件被隱藏
		headerView.setPadding(0, -headerViewHeight, 0, 0);
		//新增頭佈局
		addHeaderView(headerView);
	}
	
	/**
	 * 初始化旋轉動畫
	 */
	private void initRotateAnimation() {

		upAnimation = new RotateAnimation(0, -180, 
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		upAnimation.setDuration(300);
		upAnimation.setFillAfter(true);

		downAnimation = new RotateAnimation(-180, -360, 
				RotateAnimation.RELATIVE_TO_SELF, 0.5f,
				RotateAnimation.RELATIVE_TO_SELF, 0.5f);
		downAnimation.setDuration(300);
		downAnimation.setFillAfter(true);
	}

	//初始化底佈局,與頭佈局同理
	private void initFooterView() {
		footerView = View.inflate(getContext(), R.layout.foot_custom_listview, null);
		footerView.measure(0, 0);
		footerViewHeight = footerView.getMeasuredHeight();
		footerView.setPadding(0, -footerViewHeight, 0, 0);
		addFooterView(footerView);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent ev) {
		switch (ev.getAction()) {
		case MotionEvent.ACTION_DOWN:
			//獲取按下時y座標
			downY = (int) ev.getY();
			break;
		case MotionEvent.ACTION_MOVE:
			
			if(currentState==REFRESHING){
				//如果當前處在滑動狀態,則不做處理
				break;
			}
			//手指滑動偏移量
			int deltaY = (int) (ev.getY() - downY);

			//獲取新的padding值
			int paddingTop = -headerViewHeight + deltaY;
			if(paddingTop>-headerViewHeight && getFirstVisiblePosition()==0){
				//向下滑,且處於頂部,設定padding值,該方法實現了頂佈局慢慢滑動顯現
				headerView.setPadding(0, paddingTop, 0, 0);

				if(paddingTop>=0 && currentState==PULL_REFRESH){
					//從下拉重新整理進入鬆開重新整理狀態
					currentState = RELEASE_REFRESH;
					//重新整理頭佈局
					refreshHeaderView();
				}else if (paddingTop<0 && currentState==RELEASE_REFRESH) {
					//進入下拉重新整理狀態
					currentState = PULL_REFRESH;
					refreshHeaderView();
				}
				super.onTouchEvent(ev);	
				return true;//攔截TouchMove,不讓listview處理該次move事件,會造成listview無法滑動
			}
			
			
			break;
		case MotionEvent.ACTION_UP:
			if(currentState==PULL_REFRESH){
				//仍處於下拉重新整理狀態,未滑動一定距離,不載入資料,隱藏headView
				headerView.setPadding(0, -headerViewHeight, 0, 0);
			}else if (currentState==RELEASE_REFRESH) {
				//滑倒一定距離,顯示無padding值的headcView
				headerView.setPadding(0, 0, 0, 0);
				//設定狀態為重新整理
				currentState = REFRESHING;

				//重新整理頭部佈局
				refreshHeaderView();
				
				if(listener!=null){
					//介面回撥載入資料
					listener.onPullRefresh();
				}
			}
			break;
		}
		return super.onTouchEvent(ev);
	}
	
	/**
	 * 根據currentState來更新headerView
	 */
	private void refreshHeaderView(){
		switch (currentState) {
		case PULL_REFRESH:
			tv_state.setText("下拉重新整理");
			iv_arrow.startAnimation(downAnimation);
			break;
		case RELEASE_REFRESH:
			tv_state.setText("鬆開重新整理");
			iv_arrow.startAnimation(upAnimation);
			break;
		case REFRESHING:
			iv_arrow.clearAnimation();//因為向上的旋轉動畫有可能沒有執行完
			iv_arrow.setVisibility(View.INVISIBLE);
			pb_rotate.setVisibility(View.VISIBLE);
			tv_state.setText("正在重新整理...");
			break;
		}
	}
	
	/**
	 * 完成重新整理操作,重置狀態,在你獲取完資料並更新完adater之後,去在UI執行緒中呼叫該方法
	 */
	public void completeRefresh(){
		if(isLoadingMore){
			//重置footerView狀態
			footerView.setPadding(0, -footerViewHeight, 0, 0);
			isLoadingMore = false;
		}else {
			//重置headerView狀態
			headerView.setPadding(0, -headerViewHeight, 0, 0);
			currentState = PULL_REFRESH;
			pb_rotate.setVisibility(View.INVISIBLE);
			iv_arrow.setVisibility(View.VISIBLE);
			tv_state.setText("下拉重新整理");
			tv_time.setText("最後重新整理:"+getCurrentTime());
		}
	}
	
	/**
	 * 獲取當前系統時間,並格式化
	 * @return
	 */
	private String getCurrentTime(){
		SimpleDateFormat format = new SimpleDateFormat("yy-MM-dd HH:mm:ss");
		return format.format(new Date());
	}
	
	private OnRefreshListener listener;
	public void setOnRefreshListener(OnRefreshListener listener){
		this.listener = listener;
	}
	public interface OnRefreshListener{
		void onPullRefresh();
		void onLoadingMore();
	}
	
	/**
	 * SCROLL_STATE_IDLE:閒置狀態,就是靜止狀態
	 * SCROLL_STATE_TOUCH_SCROLL:手指觸控滑動,就是按著來滑動
	 * SCROLL_STATE_FLING:快速滑動後鬆開
	 */
	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		if(scrollState==OnScrollListener.SCROLL_STATE_IDLE 
				&& getLastVisiblePosition()==(getCount()-1) &&!isLoadingMore){
			isLoadingMore = true;			
			footerView.setPadding(0, 0, 0, 0);//顯示出footerView
			setSelection(getCount());//讓listview最後一條顯示出來
			
			if(listener!=null){
				listener.onLoadingMore();
			}
		}
	}
	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		// TODO Auto-generated method stub
		
	}
}

二、監聽listview

listview.setOnRefreshListener(new OnRefreshListener() {
                      //上啦 重新整理,重新整理是把集合倒下序,最新的就顯示在最上面
			@Override
			public void onPullRefresh() {
				// TODO Auto-generated method stub
				page+=1;
				FilterSelect("",page);//載入資料方法   用引數page來進行分頁和後臺協商好一頁傳幾條資料
				listview.completeRefresh();
				flag=true;			
			}
  //下拉載入 載入延遲設定為1秒
			@Override
			public void onLoadingMore() {
				listview.postDelayed(new Runnable() {

					@Override
					public void run() {
						page+=1;
						FilterSelect("",page);
						listview.completeRefresh();
					}
				}, 1000L);

			}
		});
//傳送請求 填充資料
private void FilterSelect(String key,int page){
		url=url+"&type="+key+"&page="+page;
		System.out.println(url);
		StringRequest param=new StringRequest(Method.GET,url,new Response.Listener<String>() {
			@Override
			public void onResponse(String response) {
				// TODO Auto-generated method stub	
				Gson gson=new Gson();				 	
				root=gson.fromJson(response.toString(), GoodsRoot.class);
				if(root.status==1)
				{
					//     	  data=root.data;
					//     	  addData=data;
					if(flag){
						List<GoodsDataBean> data=root.data;
						Collections.reverse(data);
						addData.addAll(data);
					}
					else addData.addAll(root.data);


					adapter=new GameDetailsAdapter(ProductDetails.this,addData);
					listview.setAdapter(adapter);


				}
				else 
					Toast.makeText(ProductDetails.this, "暫無最新商品", Toast.LENGTH_SHORT).show();
			}
		},null);
		requestdata.add(param);
		url=upurl;
	}