zoukankan      html  css  js  c++  java
  • 自己实现一个下拉刷新的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>  
  • 相关阅读:
    linux 服务器---FastDFS分布式文件服务器配置
    JFinal getModel方法(从页面表单中获取Model对象)+数据库存储问题
    实现Callable接口。带返回值的线程
    Spring 自动化装配Bean
    Spring--基于代理类ProxyFactoryBean的AOP实现
    Jfinal中的validator理解/详解
    Jfinal中的文件上传
    HotSpot学习(二):虚拟机的启动过程源码解析
    HotSpot学习(一):编译、启动与调试
    Netty的对象池
  • 原文地址:https://www.cnblogs.com/bbglz/p/5308078.html
Copyright © 2011-2022 走看看