Android中下拉刷新和加载更多的实现方式

首先需要明确的是下拉刷新是一个布局文件是作为ListView的头布局HeaderView和加载更多的布局文件是作为ListView的脚布局

头布局:

<?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="wrap_content"
    android:orientation="horizontal">

    <FrameLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="30dp">

        <ImageView
            android:id="@+id/iv_arr"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:src="@drawable/common_listview_headview_red_arrow"/>

        <ProgressBar
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:visibility="invisible"
            android:id="@+id/progressBar"
            android:layout_gravity="center" />

    </FrameLayout>



    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:gravity="center"
        android:orientation="vertical">

        <TextView
            android:id="@+id/tv_refresh"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="20sp"
            android:textColor="#f00"
            android:text="下拉刷新"/>

        <TextView
            android:id="@+id/tv_refresh_date"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="14sp"
            android:layout_marginTop="5dp"
            android:textColor="@android:color/darker_gray"
            android:text="最后刷新时间:2015-03-16 07:16:16"/>

    </LinearLayout>


</LinearLayout>

脚布局的布局文件:

<?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="wrap_content"
    android:gravity="center"
    android:orientation="horizontal" >

    <ProgressBar
        android:id="@+id/pb_pull_list_header"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:layout_margin="5dp"/>

    <TextView
        android:id="@+id/tv_pull_list_header_title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="加载中..."
        android:textColor="#ff0000"
        android:textSize="18sp" />

</LinearLayout>

我们需要重新一个RefreshListView来继承ListView

package com.example.administrator.smartbj.view;

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

import com.example.administrator.smartbj.R;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * 作者:Created by Kevin on 2016/1/16.
 * 邮箱:
 * 描述:下拉刷新的ListView
 */
public class RefreshListView extends ListView implements AbsListView.OnScrollListener {


    private static final int STATE_PULL_REFRESH = 0; //下拉刷新
    private static final int STATE_RELEASE_REFRESH = 1; //松开刷新
    private static final int STATE_REFRESHING = 2; //正在刷新

    private int mCurrentState = 0; //记录当前状态
    private float startY;
    private View mHeaderView;
    private int mHeaderViewHeight;
    private ImageView ivArr; //下拉刷新的箭头
    private ProgressBar progressBar;// 刷新进度条
    private TextView tvRefresh;// 刷新的状态
    private TextView tvRefreshDate;//最后刷新时间
    private RotateAnimation rotateUp;
    private RotateAnimation rotateDown;
    private View mFooterView;
    private int mFooterViewMeasuredHeight;


    public RefreshListView(Context context) {
        super(context);
        initHeaderView();
        initFooterView();
    }


    public RefreshListView(Context context, AttributeSet attrs) {
        super(context, attrs);
        initHeaderView();
        initFooterView();
    }

    public RefreshListView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initHeaderView();
        initFooterView();

    }

    /**
     * 初始化头布局
     */
    private void initHeaderView() {
        mHeaderView = View.inflate(getContext(), R.layout.header_refresh, null);
        this.addHeaderView(mHeaderView);

        ivArr = (ImageView) mHeaderView.findViewById(R.id.iv_arr);
        progressBar = (ProgressBar) mHeaderView.findViewById(R.id.progressBar);
        tvRefresh = (TextView) mHeaderView.findViewById(R.id.tv_refresh);
        tvRefreshDate = (TextView) mHeaderView.findViewById(R.id.tv_refresh_date);

        initArrAnim();//初始化箭头上下的动画

        mHeaderView.measure(0, 0);
        mHeaderViewHeight = mHeaderView.getMeasuredHeight();
        mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);//隐藏头布局

        tvRefreshDate.setText(getCurrentTime());
    }

    /**
     * 初始化脚布局
     */
    private void initFooterView() {
        mFooterView = View.inflate(getContext(), R.layout.refresh_listview_footer, null);
        this.addFooterView(mFooterView);

        mFooterView.measure(0, 0);
        mFooterViewMeasuredHeight = mFooterView.getMeasuredHeight();
        mFooterView.setPadding(0, -mFooterViewMeasuredHeight, 0, 0);//隐藏脚布局布局

        this.setOnScrollListener(this);
    }

    //下拉刷新的触摸事件
    @Override
    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {
            case MotionEvent.ACTION_DOWN:
                startY = ev.getRawY();
                break;

            case MotionEvent.ACTION_MOVE:

                if (startY == 0) {
                    startY = ev.getRawY();
                }

                if (mCurrentState == STATE_REFRESHING) {
                    break;
                }

                float endY = ev.getRawY();
                int dy = (int) (endY - startY + 0.5f);//偏移距离


                if (dy > 0 && getFirstVisiblePosition() == 0) {//下拉并且当前是第一个item
                    //重新设置mHeaderView的padding
                    int padding = -mHeaderViewHeight + dy;

                    mHeaderView.setPadding(0, padding, 0, 0);

                    if (padding > 0 && mCurrentState != STATE_RELEASE_REFRESH) {
                        mCurrentState = STATE_RELEASE_REFRESH;

                        refreshState();
                    } else if (padding < 0 && mCurrentState != STATE_PULL_REFRESH) {
                        mCurrentState = STATE_PULL_REFRESH;
                        refreshState();
                    }

                    return true;
                }


                break;

            case MotionEvent.ACTION_UP:
                startY = 0; //重置
                if (mCurrentState == STATE_RELEASE_REFRESH) {
                    mCurrentState = STATE_REFRESHING; //正在刷新
                    mHeaderView.setPadding(0, 0, 0, 0);//隐藏头布局
                    refreshState();
                } else if (mCurrentState == STATE_PULL_REFRESH) {
                    mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);//隐藏头布局
                }
                break;
        }
        return super.onTouchEvent(ev);
    }

    private void refreshState() {
        switch (mCurrentState) {
            case STATE_PULL_REFRESH:
                tvRefresh.setText("下拉刷新");
                ivArr.setVisibility(VISIBLE);
                progressBar.setVisibility(INVISIBLE);

                ivArr.startAnimation(rotateDown);

                break;

            case STATE_RELEASE_REFRESH:
                tvRefresh.setText("松开刷新");
                ivArr.setVisibility(VISIBLE);
                progressBar.setVisibility(INVISIBLE);

                ivArr.startAnimation(rotateUp);
                break;

            case STATE_REFRESHING:
                tvRefresh.setText("正在刷新...");
                ivArr.clearAnimation();//防止件箭头因动画未结束而不消失
                ivArr.setVisibility(INVISIBLE);
                progressBar.setVisibility(VISIBLE);

                if (mListener != null) {
                    mListener.onRefresh();
                }
                break;
        }
    }

    private void initArrAnim() {

        //变为向上的箭头
        rotateUp = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        rotateUp.setDuration(500);
        rotateUp.setFillAfter(true);

        //变为向上的箭头

        rotateDown = new RotateAnimation(-180, 0, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        rotateDown.setDuration(500);
        rotateDown.setFillAfter(true);
    }

    OnRefreshListener mListener;

    public void setOnRefreshListener(OnRefreshListener onRefreshListener) {
        mListener = onRefreshListener;
    }

    public interface OnRefreshListener {
        public void onRefresh();

        public void onLoadMore();
    }

    /**
     * 刷新完成后
     */
    public void onRefreshComplete() {
        if (isLoadingMore) {//加载更多则收起加载更多
            isLoadingMore = false;
            mFooterView.setPadding(0, -mFooterViewMeasuredHeight, 0, 0);
        } else { //下拉刷新 收起下拉刷新
            mCurrentState = STATE_PULL_REFRESH;
            tvRefresh.setText("下拉刷新");
            ivArr.setVisibility(VISIBLE);
            progressBar.setVisibility(INVISIBLE);
            //隐藏下拉刷新
            mHeaderView.setPadding(0, -mHeaderViewHeight, 0, 0);

            tvRefreshDate.setText(getCurrentTime());
        }


    }

    /**
     * 获取当前时间
     *
     * @return 当前时间
     */
    public String getCurrentTime() {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA);
        return format.format(new Date());
    }

    private boolean isLoadingMore;

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        if (scrollState == SCROLL_STATE_IDLE || scrollState == SCROLL_STATE_FLING) {
            if (getLastVisiblePosition() == getCount() - 1 && !isLoadingMore) {//当划到最后一个的时候
                System.out.println("到底了....");
                this.setSelection(getCount() - 1);

                mFooterView.setPadding(0, 0, 0, 0);

                this.setSelection(getCount() - 1);
                isLoadingMore = true;

                //加载更多
                if (mListener != null) {
                    mListener.onLoadMore();
                }
            }
        }

    }

    @Override
    public void onScroll(AbsListView view, int firstVisibleItem, int visibleItemCount, int totalItemCount) {

    }

}

最后再我们需要实现下拉刷洗和加载更多的页面设置监听回调后实现刷新后加载数据的功能即可。

listView.setOnRefreshListener(new RefreshListView.OnRefreshListener() {
            @Override
            public void onRefresh() {
                getDataFromServer();
            }

            @Override
            public void onLoadMore() {
                if (!TextUtils.isEmpty(mMoreUrl)) {
                    getMoreDataFromServer();
                } else {
                    Toast.makeText(mActivity, "已经到最后一页了", Toast.LENGTH_SHORT).show();
                    listView.onRefreshComplete();
                }
            }
        });
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值