ListView 上拉和下拉刷新控件



转:http://blog.csdn.net/cherry609195946/article/details/8843712

个博客好想不能提供下载代码啊, 我只能把代码贴出来了...

其实你只需看用法, 不用关心具体实现,demo非常容易看懂

  1. public class CustomListViewActivity extends Activity {  
  2.     private CustomListView listview;  
  3.     private ArrayList<String> data;  
  4.     private BaseAdapter adapter;  
  5.   
  6.     /** Called when the activity is first created. */  
  7.     @Override  
  8.     public void onCreate(Bundle savedInstanceState) {  
  9.         super.onCreate(savedInstanceState);  
  10.         setContentView(R.layout.main);  
  11.           
  12.         init();  
  13.         setListener();  
  14.     }  
  15.       
  16.       
  17.     private void init(){  
  18.         data = new ArrayList<String>();  
  19.         //虚拟一些数据  
  20.         data.add("a");  
  21.         data.add("b");  
  22.         data.add("c");  
  23.         data.add("e");  
  24.         data.add("f");  
  25.         data.add("g");  
  26.         data.add("h");  
  27.         data.add("i");  
  28.         data.add("j");  
  29.         data.add("k");  
  30.         data.add("L");  
  31.         data.add("M");  
  32.         data.add("L");  
  33.         data.add("N");  
  34.         data.add("O");  
  35.         data.add("P");  
  36.         data.add("Q");  
  37.           
  38.         listview = (CustomListView) findViewById(R.id.listview);  
  39.           
  40.         adapter = new BaseAdapter(){  
  41.             @Override  
  42.             public int getCount() {  
  43.                 return data.size();  
  44.             }  
  45.   
  46.             @Override  
  47.             public Object getItem(int position) {  
  48.                 return null;  
  49.             }  
  50.   
  51.             @Override  
  52.             public long getItemId(int position) {  
  53.                 return position;  
  54.             }  
  55.   
  56.             @Override  
  57.             public View getView(int position, View convertView, ViewGroup parent) {  
  58.                 TextView textView = new TextView(getApplicationContext());  
  59.                 textView.setHeight(100);  
  60.                 textView.setTextSize(20);  
  61.                 textView.setGravity(Gravity.CENTER);  
  62.                 textView.setBackgroundColor(0x66666666);  
  63.                 textView.setTextColor(0xaaffffff);  
  64.                 textView.setText(data.get(position));  
  65.                 return textView;  
  66.             }  
  67.         };  
  68.         listview.setAdapter(adapter);  
  69.     }  
  70.       
  71.     private void setListener(){  
  72.         listview.setOnRefreshListner(new OnRefreshListner() {  
  73.             @Override  
  74.             public void onRefresh() {  
  75.                 new AsyncTask<Void, Void, ArrayList<String>>(){  
  76.                     @Override  
  77.                     protected ArrayList<String> doInBackground(Void... params) {  
  78.                         try {  
  79.                             //模拟从服务器获取数据的过程  
  80.                             Thread.sleep(1500);  
  81.                         } catch (InterruptedException e) {  
  82.                             e.printStackTrace();  
  83.                         }  
  84.                           
  85.                         ArrayList<String> virtualData = new ArrayList<String>();  
  86.                         virtualData.add("Head刷新后的新数据1");  
  87.                         virtualData.add("Head刷新后的新数据2");  
  88.                         virtualData.add("Head刷新后的新数据3");  
  89.                         virtualData.add("Head刷新后的新数据4");  
  90.                         virtualData.add("Head刷新后的新数据5");  
  91.                         virtualData.add("Head刷新后的新数据6");  
  92.                           
  93.                         return virtualData;  
  94.                     }  
  95.                     //更新UI的方法,系统自动实现  
  96.                     @Override  
  97.                     protected void onPostExecute(ArrayList<String> result) {  
  98.                         data.addAll(0,result);//注意是往前添加数据  
  99.                         adapter.notifyDataSetChanged();  
  100.                         listview.onRefreshComplete();//完成下拉刷新,这个方法要调用  
  101.                         super.onPostExecute(result);  
  102.                     }  
  103.                 }.execute();  
  104.             }  
  105.         });  
  106.         //创建FootView  
  107.         final View footer = View.inflate(CustomListViewActivity.this, R.layout.footer, null);  
  108.         listview.setOnAddFootListener(new OnAddFootListener() {  
  109.             @Override  
  110.             public void addFoot() {  
  111.                 listview.addFooterView(footer);  
  112.             }  
  113.         });  
  114.           
  115.         listview.setOnFootLoadingListener(new OnFootLoadingListener() {  
  116.             @Override  
  117.             public void onFootLoading() {  
  118.                 new AsyncTask<Void, Void, ArrayList<String>>(){  
  119.                     @Override  
  120.                     protected ArrayList<String> doInBackground(Void... params) {  
  121.                         try {  
  122.                             //模拟从服务器获取数据的过程  
  123.                             Thread.sleep(2000);  
  124.                         } catch (InterruptedException e) {  
  125.                             e.printStackTrace();  
  126.                         }  
  127.                           
  128.                         ArrayList<String> virtualData = new ArrayList<String>();  
  129.                         virtualData.add("Foot刷新后的新数据1");  
  130.                         virtualData.add("Foot刷新后的新数据2");  
  131.                         virtualData.add("Foot刷新后的新数据3");  
  132.                         virtualData.add("Foot刷新后的新数据4");  
  133.                         virtualData.add("Foot刷新后的新数据5");  
  134.                         virtualData.add("Foot刷新后的新数据6");  
  135.                         return virtualData;  
  136.                     }  
  137.   
  138.                     //在doInBackground后面执行  
  139.                     @Override  
  140.                     protected void onPostExecute(ArrayList<String> result) {    
  141.                         data.addAll(result);//这个是往后添加数据  
  142.                         adapter.notifyDataSetChanged();  
  143.                         listview.onFootLoadingComplete();//完成上拉刷新,就是底部加载完毕,这个方法要调用  
  144.                         //移除footer,这个动作不能少  
  145.                         listview.removeFooterView(footer);  
  146.                         super.onPostExecute(result);  
  147.                     }  
  148.                 }.execute();  
  149.             }  
  150.         });  
  151.     }  
  152. }  
public class CustomListViewActivity extends Activity {
    private CustomListView listview;
	private ArrayList<String> data;
	private BaseAdapter adapter;

	/** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        
        init();
        setListener();
    }
    
    
    private void init(){
        data = new ArrayList<String>();
		//虚拟一些数据
        data.add("a");
        data.add("b");
        data.add("c");
        data.add("e");
        data.add("f");
        data.add("g");
        data.add("h");
        data.add("i");
        data.add("j");
        data.add("k");
        data.add("L");
        data.add("M");
        data.add("L");
        data.add("N");
        data.add("O");
        data.add("P");
        data.add("Q");
        
        listview = (CustomListView) findViewById(R.id.listview);
        
        adapter = new BaseAdapter(){
			@Override
			public int getCount() {
				return data.size();
			}

			@Override
			public Object getItem(int position) {
				return null;
			}

			@Override
			public long getItemId(int position) {
				return position;
			}

			@Override
			public View getView(int position, View convertView, ViewGroup parent) {
				TextView textView = new TextView(getApplicationContext());
				textView.setHeight(100);
				textView.setTextSize(20);
				textView.setGravity(Gravity.CENTER);
				textView.setBackgroundColor(0x66666666);
				textView.setTextColor(0xaaffffff);
				textView.setText(data.get(position));
				return textView;
			}
        };
        listview.setAdapter(adapter);
    }
    
    private void setListener(){
    	listview.setOnRefreshListner(new OnRefreshListner() {
			@Override
			public void onRefresh() {
				new AsyncTask<Void, Void, ArrayList<String>>(){
					@Override
					protected ArrayList<String> doInBackground(Void... params) {
						try {
							//模拟从服务器获取数据的过程
							Thread.sleep(1500);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						
						ArrayList<String> virtualData = new ArrayList<String>();
						virtualData.add("Head刷新后的新数据1");
						virtualData.add("Head刷新后的新数据2");
						virtualData.add("Head刷新后的新数据3");
						virtualData.add("Head刷新后的新数据4");
						virtualData.add("Head刷新后的新数据5");
						virtualData.add("Head刷新后的新数据6");
						
						return virtualData;
					}
					//更新UI的方法,系统自动实现
					@Override
					protected void onPostExecute(ArrayList<String> result) {
						data.addAll(0,result);//注意是往前添加数据
						adapter.notifyDataSetChanged();
						listview.onRefreshComplete();//完成下拉刷新,这个方法要调用
						super.onPostExecute(result);
					}
				}.execute();
			}
		});
        //创建FootView
        final View footer = View.inflate(CustomListViewActivity.this, R.layout.footer, null);
        listview.setOnAddFootListener(new OnAddFootListener() {
			@Override
			public void addFoot() {
				listview.addFooterView(footer);
			}
		});
        
        listview.setOnFootLoadingListener(new OnFootLoadingListener() {
			@Override
			public void onFootLoading() {
				new AsyncTask<Void, Void, ArrayList<String>>(){
					@Override
					protected ArrayList<String> doInBackground(Void... params) {
						try {
							//模拟从服务器获取数据的过程
							Thread.sleep(2000);
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
						
						ArrayList<String> virtualData = new ArrayList<String>();
						virtualData.add("Foot刷新后的新数据1");
						virtualData.add("Foot刷新后的新数据2");
						virtualData.add("Foot刷新后的新数据3");
						virtualData.add("Foot刷新后的新数据4");
						virtualData.add("Foot刷新后的新数据5");
						virtualData.add("Foot刷新后的新数据6");
						return virtualData;
					}

					//在doInBackground后面执行
					@Override
					protected void onPostExecute(ArrayList<String> result) {	
						data.addAll(result);//这个是往后添加数据
						adapter.notifyDataSetChanged();
						listview.onFootLoadingComplete();//完成上拉刷新,就是底部加载完毕,这个方法要调用
						//移除footer,这个动作不能少
						listview.removeFooterView(footer);
						super.onPostExecute(result);
					}
				}.execute();
			}
		});
    }
}

 下面上listview的代码,有点长...

  1. /** 
  2.  * 支持下拉刷新和上拉刷新 
  3.  * 可自定义上啦和下拉过程的操作,推荐使用AsyncTask 
  4.  * 需自定义Foot的View,然后只需在addFoot方法中添加即可 
  5.  * @author lxj 
  6.  * 
  7.  */  
  8. public class CustomListView extends ListView implements OnScrollListener {  
  9.   
  10.     private static final int DONE = 0;  
  11.     private static final int PULL_TO_REFRESH = 1;  
  12.     private static final int RELEASE_TO_REFRESH = 2;  
  13.     private static final int REFRESHING = 3;  
  14.     private static final float RATIO = 3;// 用来设置实际间距和上边距之间的比例  
  15.   
  16.     private int state;// 当前下拉刷新的状态  
  17.   
  18.     private int firstVisibleIndex;// 在listview中第一个可以看见的item  
  19.     private View headView;  
  20.     private ImageView headArrow;  
  21.     private ProgressBar progressBar;  
  22.     private TextView headTitle;  
  23.     private TextView headLastUpdate;  
  24.     private int headContentWidth;  
  25.     private int headContentHeight;  
  26.     private Animation animation;  
  27.     private Animation reverseAnimation;  
  28.     private OnRefreshListner refreshListner;// 刷新监听器  
  29.   
  30.     private boolean isRefreshable;  
  31.     private boolean isRecored = false;// 用来记录第一次按下坐标点,在整个滑动的过程中 只记录一次  
  32.     private float startY;  
  33.     private boolean isBack = false;// 是从 松开刷新状态 来到的 下拉刷新状态  
  34.       
  35.     public CustomListView(Context context, AttributeSet attrs) {  
  36.         super(context, attrs);  
  37.         init(context);  
  38.     }  
  39.   
  40.     private void init(Context context) {  
  41.         // listview 设置滑动时缓冲背景色  
  42.         setCacheColorHint(0x00000000);  
  43.   
  44.         headView = View.inflate(context, R.layout.head, null);  
  45.   
  46.         headArrow = (ImageView) headView.findViewById(R.id.head_arrow);  
  47.         progressBar = (ProgressBar) headView.findViewById(R.id.progressbar);  
  48.         headTitle = (TextView) headView.findViewById(R.id.head_title);  
  49.         headLastUpdate = (TextView) headView  
  50.                 .findViewById(R.id.head_last_update);  
  51.   
  52.         headArrow.setMinimumWidth(50);  
  53.         headArrow.setMinimumHeight(70);  
  54.   
  55.         MeasureView(headView);  
  56.           
  57.         headContentWidth = headView.getMeasuredWidth();  
  58.         headContentHeight = headView.getMeasuredHeight();  
  59.   
  60.         headView.setPadding(0, -1*headContentHeight, 00);  
  61.         // 为listView加入顶部View  
  62.         addHeaderView(headView);  
  63.   
  64.         setOnScrollListener(this);  
  65.   
  66.         animation = new RotateAnimation(-1800, Animation.RELATIVE_TO_SELF,  
  67.                 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);  
  68.         animation.setDuration(250);  
  69.         animation.setFillAfter(true);// 设定动画结束时,停留在动画结束位置 (保留动画效果)  
  70.         animation.setInterpolator(new LinearInterpolator());// 匀速变化  
  71.   
  72.         reverseAnimation = new RotateAnimation(0, -180,  
  73.                 Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,  
  74.                 0.5f);  
  75.         reverseAnimation.setDuration(200);  
  76.         reverseAnimation.setFillAfter(true);// 设定动画结束时,停留在动画结束位置 (保留动画效果)  
  77.         reverseAnimation.setInterpolator(new LinearInterpolator());// 匀速变化  
  78.   
  79.         // 设置当前headView的状态  
  80.         state = DONE;  
  81.   
  82.         // 设置当前下拉刷新是否可用  
  83.         isRefreshable = false;  
  84.     }  
  85.       
  86.   
  87.     /** 
  88.      * 测量headView的 宽高 
  89.      *  
  90.      * @param child 
  91.      */  
  92.     private void MeasureView(View child) {  
  93.         ViewGroup.LayoutParams lp = child.getLayoutParams();  
  94.   
  95.         if (null == lp) {  
  96.             lp = new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,  
  97.                     LayoutParams.WRAP_CONTENT);  
  98.         }  
  99.   
  100.         int measureChildWidth = ViewGroup.getChildMeasureSpec(00, lp.width);  
  101.         int measureChildHeight;  
  102.   
  103.         if (lp.height > 0) {  
  104.             measureChildHeight = MeasureSpec.makeMeasureSpec(lp.height,  
  105.                     MeasureSpec.EXACTLY);  
  106.         } else {  
  107.             measureChildHeight = MeasureSpec.makeMeasureSpec(0,  
  108.                     MeasureSpec.UNSPECIFIED);  
  109.         }  
  110.   
  111.         child.measure(measureChildWidth, measureChildHeight);  
  112.   
  113.     }  
  114.   
  115.     @Override  
  116.     public boolean onTouchEvent(MotionEvent event) {  
  117.   
  118.         switch (event.getAction()) {  
  119.         case MotionEvent.ACTION_DOWN:  
  120.             if (firstVisibleIndex == 0 && !isRecored) {  
  121.                 startY = event.getY();  
  122.                 isRecored = true;  
  123.             }  
  124.   
  125.             break;  
  126.   
  127.         case MotionEvent.ACTION_MOVE:  
  128.             float tempY = event.getY();  
  129.             if (firstVisibleIndex == 0 && !isRecored) {  
  130.                 startY = tempY;  
  131.                 isRecored = true;  
  132.             }  
  133.   
  134.             if (state != REFRESHING) {  
  135.                 if (state == PULL_TO_REFRESH) {  
  136.                     // 向下拉了 从下拉刷新的状态 来到 松开刷新的状态  
  137.                     if ((tempY - startY) / RATIO >= headContentHeight  
  138.                             && (tempY - startY) > 0) {  
  139.                         state = RELEASE_TO_REFRESH;  
  140.   
  141.                         changeHeadViewOfState();  
  142.                     }  
  143.                     // 向上推了 从下拉刷新的状态 来到 刷新完成的状态  
  144.                     else if ((tempY - startY) <= 0) {  
  145.                         state = DONE;  
  146.   
  147.                         changeHeadViewOfState();  
  148.                     }  
  149.   
  150.                 } else if (state == RELEASE_TO_REFRESH) {  
  151.                     // 向上推了 还没有完全将HEADVIEW 隐藏掉(可以看到一部分)  
  152.                     // 从松开刷新的状态 来到 下拉刷新的状态  
  153.                     if ((tempY - startY) / RATIO < headContentHeight  
  154.                             && (tempY - startY) > 0) {  
  155.                         state = PULL_TO_REFRESH;  
  156.   
  157.                         changeHeadViewOfState();  
  158.                         isBack = true;  
  159.                     }  
  160.                     // 向上推了 一下子推到了最上面 从松开刷新的状态 来到 刷新完成的状态 (数据不刷新的)  
  161.                     else if ((tempY - startY) <= 0) {  
  162.                         state = DONE;  
  163.   
  164.                         changeHeadViewOfState();  
  165.                     }  
  166.   
  167.                 } else if (state == DONE) {  
  168.                     // 刷新完成的状态 来到 下拉刷新的状态  
  169.                     if ((tempY - startY) > 0) {  
  170.                         state = PULL_TO_REFRESH;  
  171.   
  172.                         changeHeadViewOfState();  
  173.                     }  
  174.                 }  
  175.   
  176.                 if (state == PULL_TO_REFRESH) {  
  177.                     headView.setPadding(  
  178.                             0,  
  179.                             (int) ((tempY - startY) / RATIO - headContentHeight),  
  180.                             00);  
  181.                 }  
  182.   
  183.                 if (state == RELEASE_TO_REFRESH) {  
  184.                     headView.setPadding(  
  185.                             0,  
  186.                             (int) ((tempY - startY) / RATIO - headContentHeight),  
  187.                             00);  
  188.                 }  
  189.   
  190.             }  
  191.   
  192.             break;  
  193.   
  194.         case MotionEvent.ACTION_UP:  
  195.             if (state != REFRESHING) {  
  196.                 if (state == PULL_TO_REFRESH) {  
  197.                     // 松手  
  198.                     state = DONE;  
  199.   
  200.                     changeHeadViewOfState();  
  201.                 }  
  202.   
  203.                 else if (state == RELEASE_TO_REFRESH) {  
  204.                     // 松手  
  205.                     state = REFRESHING;  
  206.                     changeHeadViewOfState();  
  207.   
  208.                     // 执行数据刷新方法  
  209.                     onRefresh();  
  210.                 }  
  211.             }  
  212.   
  213.             isRecored = false;  
  214.             isBack = false;  
  215.   
  216.             break;  
  217.         }  
  218.   
  219.         return super.onTouchEvent(event);  
  220.     }  
  221.   
  222.     /** 
  223.      * 执行下拉刷新 
  224.      */  
  225.     private void onRefresh() {  
  226.         if (refreshListner != null) {  
  227.             refreshListner.onRefresh();  
  228.         }  
  229.     }  
  230.   
  231.     /** 
  232.      * HeadView的状态变化效果 
  233.      */  
  234.     private void changeHeadViewOfState() {  
  235.         //   
  236.         switch (state) {  
  237.   
  238.         case PULL_TO_REFRESH:  
  239.               
  240.             headArrow.setVisibility(View.VISIBLE);  
  241.             progressBar.setVisibility(View.GONE);  
  242.             headTitle.setVisibility(View.VISIBLE);  
  243.             headLastUpdate.setVisibility(View.VISIBLE);  
  244.               
  245.             headArrow.clearAnimation();  
  246.             headTitle.setText("下拉可以刷新");  
  247.             //由 松开刷新  到  下拉刷新  
  248.             if(isBack){  
  249.                   
  250.                 headArrow.startAnimation(animation);  
  251.                 isBack = false;  
  252.             }  
  253.   
  254.             break;  
  255.   
  256.         case RELEASE_TO_REFRESH:  
  257.               
  258.             headArrow.setVisibility(View.VISIBLE);  
  259.             progressBar.setVisibility(View.GONE);  
  260.             headTitle.setVisibility(View.VISIBLE);  
  261.             headLastUpdate.setVisibility(View.VISIBLE);  
  262.               
  263.             headArrow.clearAnimation();  
  264.             headArrow.startAnimation(reverseAnimation);  
  265.               
  266.             headTitle.setText("松开可以刷新");  
  267.   
  268.             break;  
  269.   
  270.         case REFRESHING:  
  271.   
  272.             headArrow.setVisibility(View.GONE);  
  273.             progressBar.setVisibility(View.VISIBLE);  
  274.             headTitle.setVisibility(View.VISIBLE);  
  275.             headLastUpdate.setVisibility(View.VISIBLE);  
  276.               
  277.             headArrow.clearAnimation();  
  278.             headTitle.setText("正在刷新...");  
  279.               
  280.             headView.setPadding(0000);  
  281.               
  282.             break;  
  283.   
  284.         case DONE:  
  285.               
  286.             headArrow.setVisibility(View.VISIBLE);  
  287.             progressBar.setVisibility(View.GONE);  
  288.             headTitle.setVisibility(View.VISIBLE);  
  289.             headLastUpdate.setVisibility(View.VISIBLE);  
  290.               
  291.             headArrow.clearAnimation();  
  292.             headTitle.setText("下拉可以刷新");  
  293.               
  294.             headView.setPadding(0, -1 * headContentHeight, 00);  
  295.   
  296.             break;  
  297.         }  
  298.   
  299.     }  
  300.   
  301.     private int lastPos;//最后一个可见的item的位置  
  302.     private int count;//item总数,注意不是当前可见的item总数  
  303.     private boolean hasFoot = false;//是否有了Foot  
  304.     @Override  
  305.     public void onScroll(AbsListView view, int firstVisibleItem,  
  306.             int visibleItemCount, int totalItemCount) {  
  307.         firstVisibleIndex = firstVisibleItem;  
  308.         lastPos = getLastVisiblePosition();  
  309.         count = totalItemCount;  
  310.           
  311.         //因为刚进入的时候,lastPos=-1,count=0,这个时候不能让它执行onAddFoot方法  
  312.         if(lastPos==count-1 && !hasFoot && lastPos != -1){  
  313.             hasFoot = true;  
  314.             onAddFoot();  
  315.             Log.d("addFoot================","执行添加Foot....");  
  316.         }  
  317.           
  318.         Log.d("count================", count+"");  
  319.         Log.d("lastPos================", lastPos+"");  
  320.     }  
  321.   
  322.     @Override  
  323.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
  324.         if(isFootLoading)  
  325.             return;  
  326.           
  327.         if(hasFoot && scrollState==SCROLL_STATE_IDLE){  
  328.             isFootLoading = true;  
  329.             onFootLoading();  
  330.         }  
  331.     }  
  332.   
  333.     /** 
  334.      * 设置下拉刷新监听 
  335.      *  
  336.      * @param listener 
  337.      */  
  338.     public void setOnRefreshListner(OnRefreshListner listener) {  
  339.         // 设置下拉刷新可用  
  340.         isRefreshable = true;  
  341.         refreshListner = listener;  
  342.   
  343.     }  
  344.       
  345.       
  346.     //执行底部加载  
  347.     public void onFootLoading(){  
  348.         if(footLoadingListener!=null && isFootLoading)  
  349.             footLoadingListener.onFootLoading();  
  350.     }  
  351.       
  352.     public void setOnAddFootListener(OnAddFootListener addFootListener){  
  353.         onAddFootListener = addFootListener;  
  354.     }  
  355.       
  356.     //执行添加foot  
  357.     public void onAddFoot(){  
  358.         if(onAddFootListener!=null && hasFoot)  
  359.             onAddFootListener.addFoot();  
  360.     }  
  361.     //是否添加Foot的监听器,如果写在OnFootLoadingListener中会有延迟,效果不好  
  362.     //应该是先进入添加Foot的状态,再进入FootLoading的状态  
  363.     public OnAddFootListener onAddFootListener;  
  364.     //是否进入从底部加载数据的状态的监听器  
  365.     public OnFootLoadingListener footLoadingListener;  
  366.     //正在加载底部数据  
  367.     private boolean isFootLoading = false;  
  368.     public void setOnFootLoadingListener(OnFootLoadingListener footLoading){  
  369.         footLoadingListener = footLoading;  
  370.     }  
  371.   
  372.     /** 
  373.      * 下拉刷新监听器 
  374.      * @author lxj 
  375.      * 
  376.      */  
  377.     public interface OnRefreshListner {  
  378.         /** 
  379.          * 下拉刷新的时候,在这里执行获取数据的过程 
  380.          */  
  381.         void onRefresh();  
  382.     }  
  383.       
  384.     /** 
  385.      * 上拉刷新监听器 
  386.      * @author lxj 
  387.      * 
  388.      */  
  389.     public interface OnFootLoadingListener{  
  390.         /** 
  391.          * 这里是执行后台获取数据的过程 
  392.          */  
  393.         void onFootLoading();  
  394.     }  
  395.       
  396.     /** 
  397.      * 添加Foot的监听器 
  398.      * @author lxj 
  399.      * 
  400.      */  
  401.     public interface OnAddFootListener{  
  402.         /** 
  403.          * 这里是用户addFootView的操作 
  404.          */  
  405.         void addFoot();  
  406.     }  
  407.       
  408.     /** 
  409.      * 底部数据加载完成,用户需要加入一个removeFootView的操作 
  410.      */  
  411.     public void onFootLoadingComplete(){  
  412.         hasFoot = false;  
  413.         isFootLoading = false;  
  414.     }  
  415.   
  416.     /** 
  417.      * 上拉刷新完成时 所执行的操作,更改状态,隐藏head 
  418.      */  
  419.     public void onRefreshComplete() {  
  420.         state = DONE;  
  421.         changeHeadViewOfState();  
  422.   
  423.         headLastUpdate.setText("最后刷新时间: " + new Date().toLocaleString());  
  424.     }  
  425.   
  426.     @Override  
  427.     public void setAdapter(ListAdapter adapter) {  
  428.   
  429.         headLastUpdate.setText("最后刷新时间: " + new Date().toLocaleString());  
  430.           
  431.         super.setAdapter(adapter);  
  432.     }  
  433. }  
/**
 * 支持下拉刷新和上拉刷新
 * 可自定义上啦和下拉过程的操作,推荐使用AsyncTask
 * 需自定义Foot的View,然后只需在addFoot方法中添加即可
 * @author lxj
 *
 */
public class CustomListView extends ListView implements OnScrollListener {

	private static final int DONE = 0;
	private static final int PULL_TO_REFRESH = 1;
	private static final int RELEASE_TO_REFRESH = 2;
	private static final int REFRESHING = 3;
	private static final float RATIO = 3;// 用来设置实际间距和上边距之间的比例

	private int state;// 当前下拉刷新的状态

	private int firstVisibleIndex;// 在listview中第一个可以看见的item
	private View headView;
	private ImageView headArrow;
	private ProgressBar progressBar;
	private TextView headTitle;
	private TextView headLastUpdate;
	private int headContentWidth;
	private int headContentHeight;
	private Animation animation;
	private Animation reverseAnimation;
	private OnRefreshListner refreshListner;// 刷新监听器

	private boolean isRefreshable;
	private boolean isRecored = false;// 用来记录第一次按下坐标点,在整个滑动的过程中 只记录一次
	private float startY;
	private boolean isBack = false;// 是从 松开刷新状态 来到的 下拉刷新状态
	
	public CustomListView(Context context, AttributeSet attrs) {
		super(context, attrs);
		init(context);
	}

	private void init(Context context) {
		// listview 设置滑动时缓冲背景色
		setCacheColorHint(0x00000000);

		headView = View.inflate(context, R.layout.head, null);

		headArrow = (ImageView) headView.findViewById(R.id.head_arrow);
		progressBar = (ProgressBar) headView.findViewById(R.id.progressbar);
		headTitle = (TextView) headView.findViewById(R.id.head_title);
		headLastUpdate = (TextView) headView
				.findViewById(R.id.head_last_update);

		headArrow.setMinimumWidth(50);
		headArrow.setMinimumHeight(70);

		MeasureView(headView);
		
		headContentWidth = headView.getMeasuredWidth();
		headContentHeight = headView.getMeasuredHeight();

		headView.setPadding(0, -1*headContentHeight, 0, 0);
		// 为listView加入顶部View
		addHeaderView(headView);

		setOnScrollListener(this);

		animation = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF,
				0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
		animation.setDuration(250);
		animation.setFillAfter(true);// 设定动画结束时,停留在动画结束位置 (保留动画效果)
		animation.setInterpolator(new LinearInterpolator());// 匀速变化

		reverseAnimation = new RotateAnimation(0, -180,
				Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,
				0.5f);
		reverseAnimation.setDuration(200);
		reverseAnimation.setFillAfter(true);// 设定动画结束时,停留在动画结束位置 (保留动画效果)
		reverseAnimation.setInterpolator(new LinearInterpolator());// 匀速变化

		// 设置当前headView的状态
		state = DONE;

		// 设置当前下拉刷新是否可用
		isRefreshable = false;
	}
	

	/**
	 * 测量headView的 宽高
	 * 
	 * @param child
	 */
	private void MeasureView(View child) {
		ViewGroup.LayoutParams lp = child.getLayoutParams();

		if (null == lp) {
			lp = new ViewGroup.LayoutParams(LayoutParams.FILL_PARENT,
					LayoutParams.WRAP_CONTENT);
		}

		int measureChildWidth = ViewGroup.getChildMeasureSpec(0, 0, lp.width);
		int measureChildHeight;

		if (lp.height > 0) {
			measureChildHeight = MeasureSpec.makeMeasureSpec(lp.height,
					MeasureSpec.EXACTLY);
		} else {
			measureChildHeight = MeasureSpec.makeMeasureSpec(0,
					MeasureSpec.UNSPECIFIED);
		}

		child.measure(measureChildWidth, measureChildHeight);

	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {

		switch (event.getAction()) {
		case MotionEvent.ACTION_DOWN:
			if (firstVisibleIndex == 0 && !isRecored) {
				startY = event.getY();
				isRecored = true;
			}

			break;

		case MotionEvent.ACTION_MOVE:
			float tempY = event.getY();
			if (firstVisibleIndex == 0 && !isRecored) {
				startY = tempY;
				isRecored = true;
			}

			if (state != REFRESHING) {
				if (state == PULL_TO_REFRESH) {
					// 向下拉了 从下拉刷新的状态 来到 松开刷新的状态
					if ((tempY - startY) / RATIO >= headContentHeight
							&& (tempY - startY) > 0) {
						state = RELEASE_TO_REFRESH;

						changeHeadViewOfState();
					}
					// 向上推了 从下拉刷新的状态 来到 刷新完成的状态
					else if ((tempY - startY) <= 0) {
						state = DONE;

						changeHeadViewOfState();
					}

				} else if (state == RELEASE_TO_REFRESH) {
					// 向上推了 还没有完全将HEADVIEW 隐藏掉(可以看到一部分)
					// 从松开刷新的状态 来到 下拉刷新的状态
					if ((tempY - startY) / RATIO < headContentHeight
							&& (tempY - startY) > 0) {
						state = PULL_TO_REFRESH;

						changeHeadViewOfState();
						isBack = true;
					}
					// 向上推了 一下子推到了最上面 从松开刷新的状态 来到 刷新完成的状态 (数据不刷新的)
					else if ((tempY - startY) <= 0) {
						state = DONE;

						changeHeadViewOfState();
					}

				} else if (state == DONE) {
					// 刷新完成的状态 来到 下拉刷新的状态
					if ((tempY - startY) > 0) {
						state = PULL_TO_REFRESH;

						changeHeadViewOfState();
					}
				}

				if (state == PULL_TO_REFRESH) {
					headView.setPadding(
							0,
							(int) ((tempY - startY) / RATIO - headContentHeight),
							0, 0);
				}

				if (state == RELEASE_TO_REFRESH) {
					headView.setPadding(
							0,
							(int) ((tempY - startY) / RATIO - headContentHeight),
							0, 0);
				}

			}

			break;

		case MotionEvent.ACTION_UP:
			if (state != REFRESHING) {
				if (state == PULL_TO_REFRESH) {
					// 松手
					state = DONE;

					changeHeadViewOfState();
				}

				else if (state == RELEASE_TO_REFRESH) {
					// 松手
					state = REFRESHING;
					changeHeadViewOfState();

					// 执行数据刷新方法
					onRefresh();
				}
			}

			isRecored = false;
			isBack = false;

			break;
		}

		return super.onTouchEvent(event);
	}

	/**
	 * 执行下拉刷新
	 */
	private void onRefresh() {
		if (refreshListner != null) {
			refreshListner.onRefresh();
		}
	}

	/**
	 * HeadView的状态变化效果
	 */
	private void changeHeadViewOfState() {
		// 
		switch (state) {

		case PULL_TO_REFRESH:
			
			headArrow.setVisibility(View.VISIBLE);
			progressBar.setVisibility(View.GONE);
			headTitle.setVisibility(View.VISIBLE);
			headLastUpdate.setVisibility(View.VISIBLE);
			
			headArrow.clearAnimation();
			headTitle.setText("下拉可以刷新");
			//由 松开刷新  到  下拉刷新
			if(isBack){
				
				headArrow.startAnimation(animation);
				isBack = false;
			}

			break;

		case RELEASE_TO_REFRESH:
			
			headArrow.setVisibility(View.VISIBLE);
			progressBar.setVisibility(View.GONE);
			headTitle.setVisibility(View.VISIBLE);
			headLastUpdate.setVisibility(View.VISIBLE);
			
			headArrow.clearAnimation();
			headArrow.startAnimation(reverseAnimation);
			
			headTitle.setText("松开可以刷新");

			break;

		case REFRESHING:

			headArrow.setVisibility(View.GONE);
			progressBar.setVisibility(View.VISIBLE);
			headTitle.setVisibility(View.VISIBLE);
			headLastUpdate.setVisibility(View.VISIBLE);
			
			headArrow.clearAnimation();
			headTitle.setText("正在刷新...");
			
			headView.setPadding(0, 0, 0, 0);
			
			break;

		case DONE:
			
			headArrow.setVisibility(View.VISIBLE);
			progressBar.setVisibility(View.GONE);
			headTitle.setVisibility(View.VISIBLE);
			headLastUpdate.setVisibility(View.VISIBLE);
			
			headArrow.clearAnimation();
			headTitle.setText("下拉可以刷新");
			
			headView.setPadding(0, -1 * headContentHeight, 0, 0);

			break;
		}

	}

	private int lastPos;//最后一个可见的item的位置
	private int count;//item总数,注意不是当前可见的item总数
	private boolean hasFoot = false;//是否有了Foot
	@Override
	public void onScroll(AbsListView view, int firstVisibleItem,
			int visibleItemCount, int totalItemCount) {
		firstVisibleIndex = firstVisibleItem;
		lastPos = getLastVisiblePosition();
		count = totalItemCount;
		
		//因为刚进入的时候,lastPos=-1,count=0,这个时候不能让它执行onAddFoot方法
		if(lastPos==count-1 && !hasFoot && lastPos != -1){
			hasFoot = true;
			onAddFoot();
			Log.d("addFoot================","执行添加Foot....");
		}
		
		Log.d("count================", count+"");
		Log.d("lastPos================", lastPos+"");
	}

	@Override
	public void onScrollStateChanged(AbsListView view, int scrollState) {
		if(isFootLoading)
			return;
		
		if(hasFoot && scrollState==SCROLL_STATE_IDLE){
			isFootLoading = true;
			onFootLoading();
		}
	}

	/**
	 * 设置下拉刷新监听
	 * 
	 * @param listener
	 */
	public void setOnRefreshListner(OnRefreshListner listener) {
		// 设置下拉刷新可用
		isRefreshable = true;
		refreshListner = listener;

	}
	
	
	//执行底部加载
	public void onFootLoading(){
		if(footLoadingListener!=null && isFootLoading)
			footLoadingListener.onFootLoading();
	}
	
	public void setOnAddFootListener(OnAddFootListener addFootListener){
		onAddFootListener = addFootListener;
	}
	
	//执行添加foot
	public void onAddFoot(){
		if(onAddFootListener!=null && hasFoot)
			onAddFootListener.addFoot();
	}
	//是否添加Foot的监听器,如果写在OnFootLoadingListener中会有延迟,效果不好
	//应该是先进入添加Foot的状态,再进入FootLoading的状态
	public OnAddFootListener onAddFootListener;
	//是否进入从底部加载数据的状态的监听器
	public OnFootLoadingListener footLoadingListener;
	//正在加载底部数据
	private boolean isFootLoading = false;
	public void setOnFootLoadingListener(OnFootLoadingListener footLoading){
		footLoadingListener = footLoading;
	}

	/**
	 * 下拉刷新监听器
	 * @author lxj
	 *
	 */
	public interface OnRefreshListner {
		/**
		 * 下拉刷新的时候,在这里执行获取数据的过程
		 */
		void onRefresh();
	}
	
	/**
	 * 上拉刷新监听器
	 * @author lxj
	 *
	 */
	public interface OnFootLoadingListener{
		/**
		 * 这里是执行后台获取数据的过程
		 */
		void onFootLoading();
	}
	
	/**
	 * 添加Foot的监听器
	 * @author lxj
	 *
	 */
	public interface OnAddFootListener{
		/**
		 * 这里是用户addFootView的操作
		 */
		void addFoot();
	}
	
	/**
	 * 底部数据加载完成,用户需要加入一个removeFootView的操作
	 */
	public void onFootLoadingComplete(){
		hasFoot = false;
		isFootLoading = false;
	}

	/**
	 * 上拉刷新完成时 所执行的操作,更改状态,隐藏head
	 */
	public void onRefreshComplete() {
		state = DONE;
		changeHeadViewOfState();

		headLastUpdate.setText("最后刷新时间: " + new Date().toLocaleString());
	}

	@Override
	public void setAdapter(ListAdapter adapter) {

		headLastUpdate.setText("最后刷新时间: " + new Date().toLocaleString());
		
		super.setAdapter(adapter);
	}
}

下面是布局文件:

main.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <com.test.custom.CustomListView  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="fill_parent"  
  10.         android:id="@+id/listview" />  
  11.   
  12. </LinearLayout>  
<?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.test.custom.CustomListView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:id="@+id/listview" />

</LinearLayout>
head.xml

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="wrap_content"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <RelativeLayout  
  8.         android:layout_width="fill_parent"  
  9.         android:layout_height="wrap_content"  
  10.         android:layout_marginLeft="30dp" >  
  11.   
  12.         <FrameLayout  
  13.             android:layout_width="wrap_content"  
  14.             android:layout_height="wrap_content"  
  15.             android:layout_centerVertical="true" >  
  16.   
  17.             <ImageView  
  18.                 android:id="@+id/head_arrow"  
  19.                 android:layout_width="wrap_content"  
  20.                 android:layout_height="wrap_content"  
  21.                 android:layout_gravity="center"  
  22.                 android:background="@drawable/arrow" />  
  23.   
  24.             <ProgressBar  
  25.                 android:id="@+id/progressbar"  
  26.                 style="?android:attr/progressBarStyleSmall"  
  27.                 android:layout_width="wrap_content"  
  28.                 android:layout_height="wrap_content"  
  29.                 android:layout_gravity="center"  
  30.                 android:visibility="gone" />  
  31.         </FrameLayout>  
  32.   
  33.         <LinearLayout  
  34.             android:layout_width="wrap_content"  
  35.             android:layout_height="wrap_content"  
  36.             android:layout_centerHorizontal="true"  
  37.             android:gravity="center_horizontal"  
  38.             android:orientation="vertical" >  
  39.   
  40.             <TextView  
  41.                 android:id="@+id/head_title"  
  42.                 android:layout_width="wrap_content"  
  43.                 android:layout_height="wrap_content"  
  44.                 android:text="下拉可以刷新"  
  45.                 android:textColor="#666666"  
  46.                 android:textSize="20sp" />  
  47.   
  48.             <TextView  
  49.                 android:id="@+id/head_last_update"  
  50.                 android:layout_width="wrap_content"  
  51.                 android:layout_height="wrap_content"  
  52.                 android:layout_marginTop="3dp"  
  53.                 android:text="最后更新时间:"  
  54.                 android:textColor="#666666"  
  55.                 android:textSize="10sp" />  
  56.         </LinearLayout>  
  57.     </RelativeLayout>  
  58.   
  59. </LinearLayout>  
<?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="wrap_content"
    android:orientation="vertical" >

    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp" >

        <FrameLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerVertical="true" >

            <ImageView
                android:id="@+id/head_arrow"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:background="@drawable/arrow" />

            <ProgressBar
                android:id="@+id/progressbar"
                style="?android:attr/progressBarStyleSmall"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:visibility="gone" />
        </FrameLayout>

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:gravity="center_horizontal"
            android:orientation="vertical" >

            <TextView
                android:id="@+id/head_title"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="下拉可以刷新"
                android:textColor="#666666"
                android:textSize="20sp" />

            <TextView
                android:id="@+id/head_last_update"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_marginTop="3dp"
                android:text="最后更新时间:"
                android:textColor="#666666"
                android:textSize="10sp" />
        </LinearLayout>
    </RelativeLayout>

</LinearLayout>

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="match_parent"  
  5.     android:orientation="horizontal"  
  6.     android:gravity="center" >  
  7.       
  8.     <ProgressBar  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.          />  
  12.     <TextView android:layout_width="wrap_content"  
  13.         android:layout_height="wrap_content"  
  14.         android:paddingLeft="10dip"  
  15.         android:text="正在加载中..."  
  16.         android:textSize="20sp"/>  
  17.   
  18. </LinearLayout>  
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="horizontal"
    android:gravity="center" >
    
    <ProgressBar
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
         />
    <TextView android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="10dip"
        android:text="正在加载中..."
        android:textSize="20sp"/>

</LinearLayout>


本着一条龙服务的原则, 下面连箭头图片都给你搞上...点我下载箭头箭头就在前面那个空格区域(3个点的后面),晕啊,抓狂箭头是白色的看不到,,,你在那里用鼠标拖一下就出来了,或者到我空间相册下载....


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值