Android ListView 下拉刷新demo


简单的下拉list view 下拉刷新demo 直接复制即可



1.PullToRefreshListView.java 自定义 ListView 实现下拉刷新Java文件;

 

package com.example.myapplication666;

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.LinearInterpolator;
import android.view.animation.RotateAnimation;
import android.widget.AbsListView;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;

import androidx.recyclerview.widget.RecyclerView;

public class PullToRefreshListView extends ListView implements View.OnClickListener, AbsListView.OnScrollListener {
    /**
     * 下拉状态
     */
    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 String TAG = "PullRefreshListView";

    private OnRefreshListener mOnRefreshListener;

    /**
     * 组件滑动监听器 scroll  当view在进行下拉滑动的时候,判断滑动的距离,
     * 如果达到可以进行刷新的临界点时候,回调当前接口中的方法
     * Listener that will receive notifications every time the list scrolls.
     */
    private OnScrollListener mOnScrollListener;

    //下拉刷新的的头部view
    private LinearLayout mRefreshView;
    private ImageView mRefreshViewImage;
    private ProgressBar mRefreshViewProgress;
    private TextView mRefreshViewText;
    private TextView mRefreshViewLastUpdated;


    private int mRefreshState;
    private int mCurrentScrollState;

    private RotateAnimation mFlipAnimation;
    private RotateAnimation mReverseFlipAnimation;

    private int mRefreshViewHeight;
    private int mRefreshOriginalTopPadding;
    private int mLastMotionY;

    public PullToRefreshListView(Context context) {
        super(context);
        init(context);
    }

    public PullToRefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init(context);
    }

    private void init(Context context) {
        mFlipAnimation = new RotateAnimation(0, -180,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        mFlipAnimation.setInterpolator(new LinearInterpolator());
        mFlipAnimation.setDuration(250);
        mFlipAnimation.setFillAfter(true);
        mReverseFlipAnimation = new RotateAnimation(-180, 0,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f,
                RotateAnimation.RELATIVE_TO_SELF, 0.5f);
        mReverseFlipAnimation.setInterpolator(new LinearInterpolator());
        mReverseFlipAnimation.setDuration(250);
        mReverseFlipAnimation.setFillAfter(true);

        mRefreshView = (LinearLayout) View.inflate(context, R.layout.pull_to_refresh_header, null);
        mRefreshViewText = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);
        mRefreshViewImage = (ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);
        mRefreshViewProgress = (ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);
        mRefreshViewLastUpdated = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);

        mRefreshState = PULL_TO_REFRESH;
        mRefreshViewImage.setMinimumHeight(50); //设置下拉最小的高度为50

        setFadingEdgeLength(0);
        setHeaderDividersEnabled(false);

        //把refreshview加入到listview的头部
        addHeaderView(mRefreshView);
        super.setOnScrollListener(this);
        mRefreshView.setOnClickListener(this);

        mRefreshView.measure(MeasureSpec.UNSPECIFIED, MeasureSpec.UNSPECIFIED);
        mRefreshViewHeight = mRefreshView.getMeasuredHeight();
        mRefreshOriginalTopPadding = -mRefreshViewHeight;

        resetHeaderPadding();
    }

    /**
     * Set the listener that will receive notifications every time the list scrolls.
     *
     * @param l  The scroll listener.
     */
    @Override
    public void setOnScrollListener(OnScrollListener l) {
        mOnScrollListener = l;
    }

    /**
     * 注册listview下拉刷新回到接口
     * Register a callback to be invoked when this list should be refreshed.
     *
     * @param onRefreshListener  The callback to run.
     */
    public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
        mOnRefreshListener = onRefreshListener;
    }

    /**
     * 进行设置设置上一次更新的时候
     *
     * Set a text to represent when the list was last updated.
     * @param lastUpdated Last updated at.
     */
    public void setLastUpdated(CharSequence lastUpdated) {
        if (lastUpdated != null) {
            mRefreshViewLastUpdated.setVisibility(View.VISIBLE);
            mRefreshViewLastUpdated.setText(lastUpdated);
        } else {
            mRefreshViewLastUpdated.setVisibility(View.GONE);
        }
    }

    /**
     * touch事件处理
     * @param event
     * @return
     */
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        final int y = (int) event.getY();
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastMotionY = y;
                break;
            case MotionEvent.ACTION_MOVE:
                int offsetY = (int) event.getY();
                int deltY = Math.round(offsetY - mLastMotionY);
                mLastMotionY = offsetY;

                if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
                    deltY = deltY / 2;
                    mRefreshOriginalTopPadding += deltY;
                    if (mRefreshOriginalTopPadding < -mRefreshViewHeight) {
                        mRefreshOriginalTopPadding = -mRefreshViewHeight;
                    }
                    resetHeaderPadding();
                }
                break;
            case MotionEvent.ACTION_UP:
                //当手指抬开得时候 进行判断下拉的距离 ,如果>=临界值,那么进行刷洗,否则回归原位
                if (!isVerticalScrollBarEnabled()) {
                    setVerticalScrollBarEnabled(true);
                }
                if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {
                    if (mRefreshView.getBottom() >= mRefreshViewHeight
                            && mRefreshState == RELEASE_TO_REFRESH) {
                        //准备开始刷新
                        prepareForRefresh();
                    } else {
                        // Abort refresh
                        resetHeader();
                    }
                }
                break;
        }
        return super.onTouchEvent(event);
    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
                         int visibleItemCount, int totalItemCount) {
        if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL && mRefreshState != REFRESHING) {
            if (firstVisibleItem == 0) {
                if ((mRefreshView.getBottom() >= mRefreshViewHeight)
                        && mRefreshState != RELEASE_TO_REFRESH) {
                    mRefreshViewText.setText("松开加载");
                    mRefreshViewImage.clearAnimation();
                    mRefreshViewImage.startAnimation(mFlipAnimation);
                    mRefreshState = RELEASE_TO_REFRESH;
                } else if (mRefreshView.getBottom() < mRefreshViewHeight
                        && mRefreshState != PULL_TO_REFRESH) {
                     mRefreshViewText.setText("放弃加载");
                    mRefreshViewImage.clearAnimation();
                    mRefreshViewImage.startAnimation(mReverseFlipAnimation);
                    mRefreshState = PULL_TO_REFRESH;
                }
            }
        }

        if (mOnScrollListener != null) {
            mOnScrollListener.onScroll(view, firstVisibleItem, visibleItemCount, totalItemCount);
        }
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        mCurrentScrollState = scrollState;

        if (mOnScrollListener != null) {
            mOnScrollListener.onScrollStateChanged(view, scrollState);
        }
    }

    /**
     * Sets the header padding back to original size.
     */
    private void resetHeaderPadding() {
        mRefreshView.setPadding(
                mRefreshView.getPaddingLeft(),
                mRefreshOriginalTopPadding,
                mRefreshView.getPaddingRight(),
                mRefreshView.getPaddingBottom());
    }

    public void prepareForRefresh() {
        if (mRefreshState != REFRESHING) {
            mRefreshState = REFRESHING;

            mRefreshOriginalTopPadding = 0;
            resetHeaderPadding();

            mRefreshViewImage.clearAnimation();
            mRefreshViewImage.setVisibility(View.GONE);
            mRefreshViewProgress.setVisibility(View.VISIBLE);
            mRefreshViewText.setText("数据加载中");

            onRefresh();
        }
    }

    private void resetHeader() {
        mRefreshState = PULL_TO_REFRESH;

        mRefreshOriginalTopPadding = -mRefreshViewHeight;
        resetHeaderPadding();

        mRefreshViewImage.clearAnimation();
     //   mRefreshViewImage.setVisibility(View.VISIBLE);
        mRefreshViewProgress.setVisibility(View.GONE);
        mRefreshViewText.setText("下拉刷新");
    }

    /**
     * 开始回调刷新
     */
    public void onRefresh() {
        Log.d(TAG, "onRefresh");
        if (mOnRefreshListener != null) {
            mOnRefreshListener.onRefresh();
        }
    }

    /**
     * Resets the list to a normal state after a refresh.
     */
    public void onRefreshComplete() {
        Log.d(TAG, "onRefreshComplete");

        resetHeader();
    }

    @Override
    public void onClick(View v) {
        Log.d(TAG, "onClick");
    }

    /**
     * Interface definition for a callback to be invoked when list should be
     * refreshed.
     */
    public interface OnRefreshListener {
        /**
         * Called when the list should be refreshed.
         * <p>
         * A call to {@link PullToRefreshListView #onRefreshComplete()} is
         * expected to indicate that the refresh has completed.
         */
        public void onRefresh();
    }
}

2.pull_to_refresh_header.xml  下拉刷新功能布局文件;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/pull_to_refresh_header"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:background="#F3F3F3"
    android:orientation="vertical" >
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:paddingTop="23dip" >
        <LinearLayout
            android:id="@+id/pull_to_refresh_view"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerHorizontal="true"
            android:orientation="vertical" >
            <TextView
                android:id="@+id/pull_to_refresh_text"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:gravity="center"
                android:text=""
                android:textColor="#777777"
                android:textSize="16sp" />
            <TextView
                android:id="@+id/pull_to_refresh_updated_at"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_gravity="center"
                android:gravity="center"
                android:text="请稍后"
                android:textColor="#999999"
                android:textSize="14sp" />
        </LinearLayout>
        <ProgressBar
            android:id="@+id/pull_to_refresh_progress"
            android:layout_width="30dip"
            android:layout_height="30dip"
            android:layout_marginRight="22dip"
            android:layout_marginTop="5dip"
            android:layout_toLeftOf="@+id/pull_to_refresh_view"
            android:indeterminate="true"
            />
        <ImageView
            android:visibility="gone"

            android:id="@+id/pull_to_refresh_image"
            android:layout_width="32dip"
            android:layout_height="32dip"
            android:layout_marginRight="20dip"
            android:layout_marginTop="5dip"
            android:layout_toLeftOf="@+id/pull_to_refresh_view"
            android:contentDescription="@string/app_name"
            android:gravity="center"
            android:src="@drawable/ic_launcher_background" />
    </RelativeLayout>
    <View
        android:layout_width="fill_parent"
        android:layout_height="15dip" />
</LinearLayout>
3.MainActivity.java 主类 加载数据适配器显示自定义 ListView ;

import static java.lang.Thread.sleep;

import androidx.annotation.NonNull;
import androidx.annotation.UiThread;
import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        PullToRefreshListView p = findViewById(R.id.lv);
        String[] sp = {"1", "2", "3", "4", "5", "6", "7", "8", "9",};

        Myadapter myAdapter = new Myadapter(this, sp);

        p.setAdapter(myAdapter);

        //下拉后加载新数据回调
        p.setOnRefreshListener(new PullToRefreshListView.OnRefreshListener() {
            @Override
            public void onRefresh() {


                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        MainActivity.this.runOnUiThread(new Runnable() {
                            @Override
                            public void run() {

                                //加载完成回调隐藏头布局
                                p.onRefreshComplete();
                                Toast.makeText(getApplicationContext(), "加载完成", Toast.LENGTH_SHORT).show();


                            }
                        });

                    }
                }).start();
            }
        });


    }
}

4.activity_main.xml 主类布局文件加载自定义 PullToRefreshListView;

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.example.myapplication666.PullToRefreshListView
        android:id="@+id/lv"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />

</LinearLayout>
5.Myadapter.java 适配器代码;
package com.example.myapplication666;

import static android.content.Context.MODE_PRIVATE;

import android.content.Context;
import android.content.SharedPreferences;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.TextView;


public class Myadapter extends BaseAdapter {

    Context context;
    private String[] sp;
    SharedPreferences sharedPreferences;

    public Myadapter(Context context, String[] sp) {

        this.context = context;
        this.sp = sp;
        sharedPreferences = context.getSharedPreferences("sp", MODE_PRIVATE);

    }

    @Override
    public int getCount() {
        return sp.length;
    }

    @Override
    public Object getItem(int position) {
        return sp[position];
    }

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

    @Override
    public View getView(final int position, View convertView, ViewGroup parent) {

        Holder holder = null;
        if (convertView == null) {

            convertView = View.inflate(context, R.layout.layout, null);
            holder = new Holder();
            holder.name = convertView.findViewById(R.id.xs);
            convertView.setTag(holder);

        } else {

            holder = (Holder) convertView.getTag();

        }


        holder.name.setText(sp[position]);


        return convertView;
    }

    class Holder {

        TextView name;


    }
}

6.layout.xml listview item 布局文件;

<?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">
    <TextView
        android:id="@+id/xs"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值