自定义ListView的上拉刷新和下拉加载

本文分享了作者自定义实现的ListView组件,该组件具备下拉加载和上拉刷新功能。文章详细介绍了如何通过监听触摸事件和滚动状态,实现不同状态下的刷新提示,并通过线程模拟数据加载过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

今天自己写了一个 自定义ListView实现下拉加载和上拉刷新,别的不说了直接上代码

package com.wd.tech.mview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.Handler;
import android.os.Message;
import android.util.AttributeSet;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AbsListView;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;

import com.wd.tech.R;

public class MyListView extends ListView implements AbsListView.OnScrollListener {
    private View headView;
    private int headViewViewHeight;
    private int downY;
    private int moveY;
    private Context mContext;
    //设置3种下拉刷新状态
    public final int DOWN_REFRESH = 1;
    public final int RELEASE_REFRESH = 2;
    public final int REFRESHING = 3;
    private int currentState = DOWN_REFRESH;//当前状态是下拉刷新
    private TextView tvStateHeader;
    private View footerView;
    private TextView tvFooter;
    private int footerViewHeight;

    private int LOAD_MORE_ING = 1;
    private int LOAD_MORE = 2;
    private int currentStateFooter = LOAD_MORE;

    public MyListView(Context context) {
        super(context);
        inIt(context);
    }

    public MyListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        inIt(context);
    }

    public MyListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        inIt(context);
    }

    private void inIt(Context context) {
        this.mContext = context;
        initHeadView(context);//初始化头部布局
        initFooterView(context);//初始化脚布View
        setOnScrollListener(this); //设置滑动监听
    }

    private void initHeadView(Context context) {
        //找到头部的布局
        headView = LayoutInflater.from(context).inflate(R.layout.layout_head_view, null);
        //找到布局中的控件
        tvStateHeader = (TextView) headView.findViewById(R.id.tvhead);
        //调用onMeasure方式测量控件大小
        headView.measure(0, 0);
        //获取头部view的高度
        headViewViewHeight = headView.getMeasuredHeight();
        //为头部veiw设置内边距,通过内边距的高度设置为负数这样实现隐藏view的高度
        headView.setPadding(0, -headViewViewHeight, 0, 0);
        //把view添加到头部中  
        addHeaderView(headView);
    }
    

    //同添加头部的view一样
    private void initFooterView(Context context) {
        footerView = View.inflate(context, R.layout.layout_head_view, null);
        tvFooter = (TextView)footerView.findViewById(R.id.tvhead);
        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:
                 //当手机移动的时候获取这一点的y轴
                moveY = (int) ev.getY();
                //用移动当前的y轴减去当手指按下的y轴得出值
                int instance = moveY - downY;
                 //然后判断当前的条目是不是第一条 并且当前状态不为正在刷新状态进行刷新
                if (instance > 0 && getFirstVisiblePosition() == 0 && currentState != REFRESHING) {
                    int paddingTop = -headViewViewHeight + instance;
                    if (paddingTop < 0) {//&& currentStateHeader != RELEASE_REFRESH
                        currentState = DOWN_REFRESH;
                        tvStateHeader.setText("下拉刷新");
                    } else if (paddingTop > 0) {//&& currentStateHeader == DOWN_REFRESH
                        currentState = RELEASE_REFRESH;
                        tvStateHeader.setText("释放刷新");
                    }
                    //对paddingTop进行限制,paddingTop<=3*headerViewHeight
                    if (paddingTop > 3 * headViewViewHeight) {
                        headView.setPadding(0, 3 * headViewViewHeight, 0, 0);
                    } else {
                        headView.setPadding(0, paddingTop, 0, 0);
                    }
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                if (currentState == RELEASE_REFRESH) {
                    //刷新中
                    currentState = REFRESHING;
                    headView.setPadding(0, 0, 0, 0);
                    tvStateHeader.setText("刷新中");
                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            try {
                                Thread.sleep(2000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            Message message = new Message();
                            message.what=1;
                            handler.sendMessage(message);
                        }
                    }).start();
                   /* if (onRefreshListener != null) {
                        onRefreshListener.refresh();
                    }*/
                } else if (currentState == DOWN_REFRESH) {
                    headView.setPadding(0, -headViewViewHeight, 0, 0);
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (scrollState == SCROLL_STATE_FLING || scrollState == SCROLL_STATE_IDLE) {
            if (getLastVisiblePosition() == getCount() - 1 && currentStateFooter == LOAD_MORE) {
                currentStateFooter = LOAD_MORE_ING;
                footerView.setPadding(0, 0, 0, 0);
                setSelection(getCount());
          /*      if (onLoadMoreListener != null) {
                    onLoadMoreListener.loadMore();
                }*/
                tvFooter.setText("上拉加载中。。。。");
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        Message message = new Message();
                        message.what=2;
                        handler.sendMessage(message);
                    }
                }).start();
            }
        }
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {
        Log.d("Tagger2", visibleItemCount + "==" + totalItemCount);
    }

    @SuppressLint("HandlerLeak")
    private Handler handler = new Handler(){

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
           int what =  msg.what;
           switch (what) {
               case 1:
                   headView.setPadding(0, -headViewViewHeight, 0, 0);
                   currentState = DOWN_REFRESH;
                   Toast.makeText(mContext,"刷新成功",Toast.LENGTH_SHORT).show();
                   break;
               case 2:
                   currentStateFooter = LOAD_MORE;
                   footerView.setPadding(0, -footerViewHeight, 0, 0);
                   break;
           }
        }
    };

}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值