自己实现一个下拉刷新的ListView

效果大笑委屈

实现一个下拉刷新的ListView

1.确定状态

下拉刷新的ListView一共有四种状态,分别是
  1. 常态(刷新完成或者是正常展示的时候)
  2. 正在下拉但是下拉的距离没有达到我们定义的可以刷新的距离(下拉可以刷新)
  3. 下拉的距离达到了可以刷新的距离(释放立即刷新)
  4. 正在刷新

2.确定实现方案

  1. 我们用一个FrameLayout包裹一个下拉刷新的头布局和一个ListView,最开始的时候使下拉刷新的头布局Margin为赋值,看不到
  2. 触摸事件拦截,当ListView的第一个Item可见并且我们向下拉的时候,拦截触摸事件
  3. 在触摸事件处理的时候,使下拉刷新的头布局和ListView的Margin变化,从而达到随手指下拉移动的效果,最开始显示的状态是“下拉可以刷新”
  4. 当下拉的距离达到可以刷新的距离的时候,我们改变状态为“释放立即刷新”
  5. 释放的时候,如果状态是“下拉可以刷新”,则直接回到初始状态,不掉用刷新的接口;如果状态是“释放立即刷新”,则调用刷新的接口,当回调刷新完成时,回到初始状态

3.代码实现

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. package com.example.myapp.view;  
  2.   
  3. import android.content.Context;  
  4. import android.util.AttributeSet;  
  5. import android.view.LayoutInflater;  
  6. import android.view.MotionEvent;  
  7. import android.view.View;  
  8. import android.widget.AdapterView;  
  9. import android.widget.FrameLayout;  
  10. import android.widget.ListAdapter;  
  11. import android.widget.ListView;  
  12. import android.widget.TextView;  
  13.   
  14. import com.example.myapp.R;  
  15.   
  16. /**  
  17.  * Created by zyr  
  18.  * DATE: 16-3-16  
  19.  * Time: 下午4:12  
  20.  * Email: yanru.zhang@renren-inc.com  
  21.  * 关于下拉刷新,我目前看到的办法是将刷新的部分和ListView包含在LinearlyLayout中,滑动的时候改变LinearlyLayout的padding  
  22.  * 感觉用header,改变ListView的header的高度应该也可行把,没有试过  
  23.  *  
  24.  *  
  25.  *  
  26.  * 下拉刷新  
  27.  * 1.往下拉,而且已经拉到最顶部  
  28.  * 2.超过一定的距离  
  29.  * 3.  
  30.  */  
  31. public class CustomPullToRefreshListView extends FrameLayout{  
  32.     private Context mContext;  
  33.     private View refreshView;  
  34.     private ListView listView;  
  35.     private TextView textView;  
  36.     private int mWidth,mHeight,mRefreshWidth,mRefreshHeight;  
  37.     private FrameLayout.LayoutParams refreshViewLayoutParams,listViewLayoutParams;  
  38.     private int downX,downY,touchX,touchY,deltaX,deltaY,startX,startY,headMoveX,headMoveY;  
  39.     private boolean isScrollDown = false;  
  40.     private int currentStatus = STATUS_REFRESH_FINISHED;  
  41.     /**  
  42.      * 下拉状态  
  43.      */  
  44.     public static final int STATUS_PULL_TO_REFRESH = 0;  
  45.     /**  
  46.      * 释放立即刷新状态  
  47.      */  
  48.     public static final int STATUS_RELEASE_TO_REFRESH = 1;  
  49.     /**  
  50.      * 正在刷新状态  
  51.      */  
  52.     public static final int STATUS_REFRESHING = 2;  
  53.     /**  
  54.      * 刷新完成或未刷新状态  
  55.      */  
  56.     public static final int STATUS_REFRESH_FINISHED = 3;  
  57.     /**  
  58.      * 下拉超过这个高度释放就可以刷新  
  59.      */  
  60.     public static final int REFRESH_HEIGHT = 200;  
  61.     /***************************    OnRefreshListener   *************************/  
  62.     public void setOnRefreshListener(OnRefreshListener onRefreshListener) {  
  63.         this.onRefreshListener = onRefreshListener;  
  64.     }  
  65.   
  66.     private OnRefreshListener onRefreshListener;  
  67.     public interface OnRefreshListener{  
  68.         void onRefresh();  
  69.     }  
  70.   
  71.     public CustomPullToRefreshListView(Context context) {  
  72.         this(context, null);  
  73.     }  
  74.   
  75.     public CustomPullToRefreshListView(Context context, AttributeSet attrs) {  
  76.         this(context, attrs, 0);  
  77.     }  
  78.   
  79.     public CustomPullToRefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {  
  80.         super(context, attrs, defStyleAttr);  
  81.         mContext = context;  
  82.         init();  
  83.     }  
  84.   
  85.     private void init() {  
  86.         LayoutInflater.from(mContext).inflate(R.layout.layout_custom_pull_to_refresh_listview, this);  
  87.         refreshView = findViewById(R.id.refresh_view);  
  88.         refreshViewLayoutParams = (FrameLayout.LayoutParams)refreshView.getLayoutParams();  
  89.         textView = (TextView)refreshView.findViewById(R.id.text_view);  
  90.         listView = (ListView)findViewById(R.id.list_view);  
  91.         listViewLayoutParams = (FrameLayout.LayoutParams)listView.getLayoutParams();  
  92.     }  
  93.   
  94.     @Override  
  95.     protected void onSizeChanged(int w, int h, int oldw, int oldh) {  
  96.         super.onSizeChanged(w, h, oldw, oldh);  
  97.         if(w!=oldw || h!=oldh){  
  98.             mWidth = w;  
  99.             mHeight = h;  
  100.             mRefreshWidth = refreshView.getMeasuredWidth();  
  101.             mRefreshHeight = refreshView.getMeasuredHeight();  
  102.             if(mRefreshHeight!=0){  
  103.                 refreshViewLayoutParams.setMargins(0,-mRefreshHeight,0,0);  
  104.                 refreshView.setLayoutParams(refreshViewLayoutParams);  
  105.             }  
  106.         }  
  107.     }  
  108.   
  109.     /**************************     ListView    ************************/  
  110.     public void setAdapter(ListAdapter adapter){  
  111.         listView.setAdapter(adapter);  
  112.     }  
  113.   
  114.     public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener){  
  115.         listView.setOnItemClickListener(onItemClickListener);  
  116.     }  
  117.   
  118.     public void setSelection(int position){  
  119.         listView.setSelection(position);  
  120.     }  
  121.   
  122.     /**************************     Touch    ************************/  
  123.     /**  
  124.      * 如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,  
  125.      * 如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件  
  126.      * @param ev  
  127.      * @return  
  128.      */  
  129.     @Override  
  130.     public boolean dispatchTouchEvent(MotionEvent ev) {  
  131.         switch (ev.getAction()){  
  132.             case MotionEvent.ACTION_DOWN:  
  133.                 downX =(int) ev.getX();  
  134.                 downY =(int) ev.getY();  
  135.                 break;  
  136.             case MotionEvent.ACTION_MOVE:  
  137.                 touchX =(int) ev.getX();  
  138.                 touchY =(int) ev.getY();  
  139.                 deltaX = touchX-downX;  
  140.                 deltaY = touchY-downY;  
  141.                 if(deltaY>=0){  
  142.                     isScrollDown = true;  
  143.                 }else{  
  144.                     isScrollDown = false;  
  145.                 }  
  146.                 break;  
  147.             case MotionEvent.ACTION_CANCEL:  
  148.             case MotionEvent.ACTION_UP:  
  149.                 downX = 0;  
  150.                 downY = 0;  
  151.                 touchX = 0;  
  152.                 touchY = 0;  
  153.                 deltaX = 0;  
  154.                 deltaY = 0;  
  155.                 startX = 0;  
  156.                 startY = 0;  
  157.                 break;  
  158.         }  
  159.         return super.dispatchTouchEvent(ev);  
  160.     }  
  161.   
  162.     @Override  
  163.     public boolean onInterceptTouchEvent(MotionEvent ev) {  
  164.         switch (ev.getAction()){  
  165.             case MotionEvent.ACTION_MOVE:  
  166.                 if(isScrollDown && listView.getFirstVisiblePosition() ==0 && listView.getScrollY() == 0){  
  167.                     currentStatus = STATUS_PULL_TO_REFRESH;  
  168.                     textView.setText("下拉可以刷新");  
  169.                     startX =(int) ev.getX();  
  170.                     startY =(int) ev.getY();  
  171.                     return true;  
  172.                 }  
  173.                 break;  
  174.         }  
  175.         return super.onInterceptTouchEvent(ev);  
  176.     }  
  177.   
  178.     @Override  
  179.     public boolean onTouchEvent(MotionEvent event) {  
  180.         switch (event.getAction()){  
  181.             case MotionEvent.ACTION_DOWN:  
  182.                 break;  
  183.             case MotionEvent.ACTION_MOVE:  
  184.                 headMoveY = (int) event.getY() - startY - mRefreshHeight;  
  185.                 refreshViewLayoutParams.setMargins(0, headMoveY, 0, 0);  
  186.                 refreshView.setLayoutParams(refreshViewLayoutParams);  
  187.                 listViewLayoutParams.setMargins(0, headMoveY + mRefreshHeight, 0, 0);  
  188.                 listView.setLayoutParams(listViewLayoutParams);  
  189.                 if(headMoveY > REFRESH_HEIGHT){  
  190.                     currentStatus = STATUS_RELEASE_TO_REFRESH;  
  191.                     textView.setText("释放立即刷新");  
  192.                 }  
  193.                 break;  
  194.             case MotionEvent.ACTION_UP:  
  195.             case MotionEvent.ACTION_CANCEL:  
  196.                 if(currentStatus == STATUS_RELEASE_TO_REFRESH){  
  197.                     currentStatus = STATUS_REFRESHING;  
  198.                     textView.setText("正在刷新。。。");  
  199.                     onRefreshListener.onRefresh();  
  200.                 }else{  
  201.                     refreshViewLayoutParams.setMargins(0, -mRefreshHeight, 0, 0);  
  202.                     refreshView.setLayoutParams(refreshViewLayoutParams);  
  203.                     listViewLayoutParams.setMargins(0,0 , 0,0);  
  204.                     listView.setLayoutParams(listViewLayoutParams);  
  205.                 }  
  206.                 break;  
  207.         }  
  208.         return super.onTouchEvent(event);  
  209.     }  
  210.   
  211.     public void onRefreshComplete(){  
  212.         if(currentStatus == STATUS_REFRESHING){  
  213.             currentStatus = STATUS_REFRESH_FINISHED;  
  214.             textView.setText("刷新成功!");  
  215.         }  
  216.         refreshViewLayoutParams.setMargins(0, -mRefreshHeight, 0, 0);  
  217.         refreshView.setLayoutParams(refreshViewLayoutParams);  
  218.         listViewLayoutParams.setMargins(0,0 , 0,0);  
  219.         listView.setLayoutParams(listViewLayoutParams);  
  220.     }  
  221. }  

[html] view plain copy
 
 在CODE上查看代码片派生到我的代码片
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="match_parent"  
  4.     android:layout_height="match_parent">  
  5.     <ListView android:id="@+id/list_view"  
  6.         android:layout_width="match_parent"  
  7.         android:layout_height="match_parent"  
  8.         android:background="@color/primary_light">  
  9.     </ListView>  
  10.     <LinearLayout android:id="@+id/refresh_view"  
  11.         android:layout_width="match_parent"  
  12.         android:layout_height="50dp"  
  13.         android:orientation="horizontal"  
  14.         android:background="@color/gray">  
  15.         <TextView android:id="@+id/text_view"  
  16.             android:layout_width="match_parent"  
  17.             android:layout_height="match_parent"  
  18.             android:gravity="center"  
  19.             android:text="Refresh"  
  20.             android:textColor="@color/white"  
  21.             android:textSize="20sp"/>  
  22.     </LinearLayout>  
  23. </FrameLayout>  
posted @ 2016-03-22 19:04  BBGL_Z  阅读(199)  评论(0编辑  收藏  举报