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

效果大笑委屈


实现一个下拉刷新的ListView

1.确定状态

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

2.确定实现方案

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

3.代码实现

package com.example.myapp.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.FrameLayout;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.TextView;

import com.example.myapp.R;

/**
 * Created by zyr
 * DATE: 16-3-16
 * Time: 下午4:12
 * Email: yanru.zhang@renren-inc.com
 * 关于下拉刷新,我目前看到的办法是将刷新的部分和ListView包含在LinearlyLayout中,滑动的时候改变LinearlyLayout的padding
 * 感觉用header,改变ListView的header的高度应该也可行把,没有试过
 *
 *
 *
 * 下拉刷新
 * 1.往下拉,而且已经拉到最顶部
 * 2.超过一定的距离
 * 3.
 */
public class CustomPullToRefreshListView extends FrameLayout{
    private Context mContext;
    private View refreshView;
    private ListView listView;
    private TextView textView;
    private int mWidth,mHeight,mRefreshWidth,mRefreshHeight;
    private FrameLayout.LayoutParams refreshViewLayoutParams,listViewLayoutParams;
    private int downX,downY,touchX,touchY,deltaX,deltaY,startX,startY,headMoveX,headMoveY;
    private boolean isScrollDown = false;
    private int currentStatus = STATUS_REFRESH_FINISHED;
    /**
     * 下拉状态
     */
    public static final int STATUS_PULL_TO_REFRESH = 0;
    /**
     * 释放立即刷新状态
     */
    public static final int STATUS_RELEASE_TO_REFRESH = 1;
    /**
     * 正在刷新状态
     */
    public static final int STATUS_REFRESHING = 2;
    /**
     * 刷新完成或未刷新状态
     */
    public static final int STATUS_REFRESH_FINISHED = 3;
    /**
     * 下拉超过这个高度释放就可以刷新
     */
    public static final int REFRESH_HEIGHT = 200;
    /***************************    OnRefreshListener   *************************/
    public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
        this.onRefreshListener = onRefreshListener;
    }

    private OnRefreshListener onRefreshListener;
    public interface OnRefreshListener{
        void onRefresh();
    }

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

    public CustomPullToRefreshListView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public CustomPullToRefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        init();
    }

    private void init() {
        LayoutInflater.from(mContext).inflate(R.layout.layout_custom_pull_to_refresh_listview, this);
        refreshView = findViewById(R.id.refresh_view);
        refreshViewLayoutParams = (FrameLayout.LayoutParams)refreshView.getLayoutParams();
        textView = (TextView)refreshView.findViewById(R.id.text_view);
        listView = (ListView)findViewById(R.id.list_view);
        listViewLayoutParams = (FrameLayout.LayoutParams)listView.getLayoutParams();
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if(w!=oldw || h!=oldh){
            mWidth = w;
            mHeight = h;
            mRefreshWidth = refreshView.getMeasuredWidth();
            mRefreshHeight = refreshView.getMeasuredHeight();
            if(mRefreshHeight!=0){
                refreshViewLayoutParams.setMargins(0,-mRefreshHeight,0,0);
                refreshView.setLayoutParams(refreshViewLayoutParams);
            }
        }
    }

    /**************************     ListView    ************************/
    public void setAdapter(ListAdapter adapter){
        listView.setAdapter(adapter);
    }

    public void setOnItemClickListener(AdapterView.OnItemClickListener onItemClickListener){
        listView.setOnItemClickListener(onItemClickListener);
    }

    public void setSelection(int position){
        listView.setSelection(position);
    }

    /**************************     Touch    ************************/
    /**
     * 如果dispatchTouchEvent返回true ,则交给这个view的onTouchEvent处理,
     * 如果dispatchTouchEvent返回 false ,则交给这个 view 的 interceptTouchEvent 方法来决定是否要拦截这个事件
     * @param ev
     * @return
     */
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_DOWN:
                downX =(int) ev.getX();
                downY =(int) ev.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                touchX =(int) ev.getX();
                touchY =(int) ev.getY();
                deltaX = touchX-downX;
                deltaY = touchY-downY;
                if(deltaY>=0){
                    isScrollDown = true;
                }else{
                    isScrollDown = false;
                }
                break;
            case MotionEvent.ACTION_CANCEL:
            case MotionEvent.ACTION_UP:
                downX = 0;
                downY = 0;
                touchX = 0;
                touchY = 0;
                deltaX = 0;
                deltaY = 0;
                startX = 0;
                startY = 0;
                break;
        }
        return super.dispatchTouchEvent(ev);
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        switch (ev.getAction()){
            case MotionEvent.ACTION_MOVE:
                if(isScrollDown && listView.getFirstVisiblePosition() ==0 && listView.getScrollY() == 0){
                    currentStatus = STATUS_PULL_TO_REFRESH;
                    textView.setText("下拉可以刷新");
                    startX =(int) ev.getX();
                    startY =(int) ev.getY();
                    return true;
                }
                break;
        }
        return super.onInterceptTouchEvent(ev);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                break;
            case MotionEvent.ACTION_MOVE:
                headMoveY = (int) event.getY() - startY - mRefreshHeight;
                refreshViewLayoutParams.setMargins(0, headMoveY, 0, 0);
                refreshView.setLayoutParams(refreshViewLayoutParams);
                listViewLayoutParams.setMargins(0, headMoveY + mRefreshHeight, 0, 0);
                listView.setLayoutParams(listViewLayoutParams);
                if(headMoveY > REFRESH_HEIGHT){
                    currentStatus = STATUS_RELEASE_TO_REFRESH;
                    textView.setText("释放立即刷新");
                }
                break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if(currentStatus == STATUS_RELEASE_TO_REFRESH){
                    currentStatus = STATUS_REFRESHING;
                    textView.setText("正在刷新。。。");
                    onRefreshListener.onRefresh();
                }else{
                    refreshViewLayoutParams.setMargins(0, -mRefreshHeight, 0, 0);
                    refreshView.setLayoutParams(refreshViewLayoutParams);
                    listViewLayoutParams.setMargins(0,0 , 0,0);
                    listView.setLayoutParams(listViewLayoutParams);
                }
                break;
        }
        return super.onTouchEvent(event);
    }

    public void onRefreshComplete(){
        if(currentStatus == STATUS_REFRESHING){
            currentStatus = STATUS_REFRESH_FINISHED;
            textView.setText("刷新成功!");
        }
        refreshViewLayoutParams.setMargins(0, -mRefreshHeight, 0, 0);
        refreshView.setLayoutParams(refreshViewLayoutParams);
        listViewLayoutParams.setMargins(0,0 , 0,0);
        listView.setLayoutParams(listViewLayoutParams);
    }
}

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <ListView android:id="@+id/list_view"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/primary_light">
    </ListView>
    <LinearLayout android:id="@+id/refresh_view"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:orientation="horizontal"
        android:background="@color/gray">
        <TextView android:id="@+id/text_view"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:text="Refresh"
            android:textColor="@color/white"
            android:textSize="20sp"/>
    </LinearLayout>
</FrameLayout>



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值