自定义ListView_下拉刷新上拉加载更多

自定义ListView实现下拉刷新和上拉自动加载

效果图:

下拉效果:

自定义ListView_下拉刷新上拉加载更多自定义ListView_下拉刷新上拉加载更多自定义ListView_下拉刷新上拉加载更多

 

上拉效果:

自定义ListView_下拉刷新上拉加载更多

 

实现原理:通过ListView的addFooter与addHeader方法,将下拉布局与上拉布局添加到ListView中,再通过设置padding属性,隐藏头部和脚部

     监听onTouchEvent事件,根据手势滑动距离,动态更改下拉布局的padding,并动态更改头布局内控件效果

     监听onScrollStateChanged,动态显示隐藏脚布局

              设置回调,提供下拉刷新与加载更多的方法

Demo:http://files.cnblogs.com/files/liujingg/PullRefreshDemo.rar

PullListView.java

import java.text.SimpleDateFormat;

import java.util.Date;



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.AbsListView.OnScrollListener;

import android.widget.ImageView;

import android.widget.LinearLayout;

import android.widget.ListView;

import android.widget.ProgressBar;

import android.widget.TextView;



/**

 * 自定义ListView,下拉刷新、上拉自动加载更多

 * @author liujing

 * @version 1.0

 */

public class PullListView extends ListView implements OnScrollListener {



    private final int PULL_DOWN_REFRESH = 0;//下拉状态

    private final int RELEASE_REFRESH = 1;//松开状态

    private final int REFRESHING = 2;//刷新中状态

    private int currentState = PULL_DOWN_REFRESH;

    private int mListViewOnScreenY = -1;

    private int downY = -1;

    

    private boolean isLoadingMore = false;

    private boolean isEnabledPullDownRefresh = false;

    private boolean isEnabledLoadMore = false;

    private OnPullDownRefresh mOnPullDownRefresh;

    

    //头布局、脚布局及高度

    private View mFootView;

    private LinearLayout mHeaderView;

    private int mFooterViewHeight;

    private int mPullDownHeaderViewHeight;

    

    //mHeaderView中组件及动画

    private View mCustomHeaderView;//用户自定义头布局

    private View mPullDownHeader;//下拉刷新头布局

    private RotateAnimation upAnimation,downAnimation;

    private ImageView ivArrow;

    private ProgressBar mProgressBar;

    private TextView tv_statue,tv_time;

    



    public PullListView(Context context) {

        this(context, null);

    }



    public PullListView(Context context, AttributeSet attrs) {

        this(context, attrs, 0);

    }



    public PullListView(Context context, AttributeSet attrs, int defStyle) {

        super(context, attrs, defStyle);

        initPullDownHeaderView();

        initLoadMoreFooterView();

    }

    

    private void initLoadMoreFooterView() {

        //加载更多的布局文件

        mFootView = View.inflate(getContext(), R.layout.pull_listview_footer,

                null);

        mFootView.measure(0, 0);//测量

        mFooterViewHeight = mFootView.getMeasuredHeight();

        //隐藏脚布局

        mFootView.setPadding(0,-mFooterViewHeight,0,0);

        addFooterView(mFootView);

        setOnScrollListener(this);

    }



    private void initPullDownHeaderView() {

        //下拉刷新的布局文件

        mHeaderView = (LinearLayout) View.inflate(getContext(),

                R.layout.pull_listview_header, null);

        mPullDownHeader = mHeaderView

                .findViewById(R.id.ll_refresh_pull_down_header);

        ivArrow = (ImageView) mHeaderView

                .findViewById(R.id.iv_refresh_header_arrow);

        mProgressBar = (ProgressBar) mHeaderView

                .findViewById(R.id.pb_refresh_header);

        tv_statue = (TextView) mHeaderView

                .findViewById(R.id.tv_refresh_header_status);

        tv_time = (TextView) mHeaderView

                .findViewById(R.id.tv_refresh_header_time);

        mPullDownHeader.measure(0, 0);//测量

        mPullDownHeaderViewHeight = mPullDownHeader.getMeasuredHeight();

        //隐藏头布局

        mPullDownHeader.setPadding(0, -mPullDownHeaderViewHeight, 0, 0);

        addHeaderView(mHeaderView);

        initAnimation();

    }

    

    /**

     * 添加额外的头布局,比如轮播图

     * @param v 自定义头布局

     */

    public void addListViewCustomHeaderView(View v) {

        mCustomHeaderView = v;

        mHeaderView.addView(mCustomHeaderView);

    }



    @Override

    public boolean onTouchEvent(MotionEvent ev) {

        switch (ev.getAction()) {

        case MotionEvent.ACTION_DOWN:

            downY = (int) ev.getY();

            break;

        case MotionEvent.ACTION_MOVE:

            if (downY == -1)

                downY = (int) ev.getY();

            //是否启用下拉刷新

            if (!isEnabledPullDownRefresh)

                break;

            if (currentState == REFRESHING)

                break;

            //解决用户添加header与下拉刷新header的冲突

            if (mCustomHeaderView != null) {

                int[] location = new int[2];

                if (mListViewOnScreenY == -1) {

                    this.getLocationOnScreen(location);

                    mListViewOnScreenY = location[1];

                }

                mCustomHeaderView.getLocationOnScreen(location);

                if (location[1] < mListViewOnScreenY) {

                    break;

                }

            }



            int moveY = (int) ev.getY();

            int diffY = (moveY - downY)/2;

            if (diffY > 0 && getFirstVisiblePosition() == 0) {

                int paddingTop = -mPullDownHeaderViewHeight + diffY;

                if (paddingTop < 0 && currentState != PULL_DOWN_REFRESH) {

                    //当前没有完全显示且当前状态为松开刷新,进入下拉刷新

                    currentState = PULL_DOWN_REFRESH;

                    refreshPullDownState();

                } else if (paddingTop > 0 && currentState != RELEASE_REFRESH) {

                    //当前完全显示且当前状态为下拉刷新,进入松开刷新

                    currentState = RELEASE_REFRESH;

                    refreshPullDownState();

                }

                mPullDownHeader.setPadding(0, paddingTop, 0, 0);

                return true;

            }else if(diffY < 0 && getLastVisiblePosition() == getCount()-1){

                //脚布局可向上滑动

                mFootView.setPadding(0,0,0,0);

            }

            break;

        case MotionEvent.ACTION_UP:

            downY = -1;

            if (currentState == PULL_DOWN_REFRESH) {

                //隐藏header

                mPullDownHeader.setPadding(0, -mPullDownHeaderViewHeight, 0, 0);

            } else if (currentState == RELEASE_REFRESH) {

                currentState = REFRESHING;

                refreshPullDownState();

                mPullDownHeader.setPadding(0, 0, 0, 0);

                //回调刷新方法

                if (mOnPullDownRefresh != null) {

                    mOnPullDownRefresh.onPullDownRefresh();

                }

            }

            break;

        }

        return super.onTouchEvent(ev);

    }

    

    /**

     * 隐藏头布局或脚布局并重置控件

     */

    public void OnRefreshDataFinish() {

        if (isLoadingMore) {

            isLoadingMore = false;

            mFootView.setPadding(0,-mFooterViewHeight,0,0);

        } else {

            ivArrow.setVisibility(View.VISIBLE);

            mProgressBar.setVisibility(View.INVISIBLE);

            tv_statue.setText("下拉刷新");

            tv_time.setText("最后刷新时间:" + getCurrentTime());

            mPullDownHeader.setPadding(0, -mPullDownHeaderViewHeight, 0, 0);

            currentState = PULL_DOWN_REFRESH;



        }

    }



    private String getCurrentTime() {

        SimpleDateFormat format = new SimpleDateFormat("HH:mm:ss");

        return format.format(new Date());

    }



    private void refreshPullDownState() {

        switch (currentState) {

        case PULL_DOWN_REFRESH:

            ivArrow.startAnimation(downAnimation);

            tv_statue.setText("下拉刷新");

            break;

        case RELEASE_REFRESH:

            ivArrow.startAnimation(upAnimation);

            tv_statue.setText("松开刷新");

            break;

        case REFRESHING:

            ivArrow.clearAnimation();

            ivArrow.setVisibility(View.INVISIBLE);

            mProgressBar.setVisibility(View.VISIBLE);

            tv_statue.setText("正在刷新");

            break;

        default:

            break;

        }

    }

    

    /**

     * 箭头旋转动画

     */

    private void initAnimation() {

        upAnimation = new RotateAnimation(0, -180, Animation.RELATIVE_TO_SELF,

                0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

        upAnimation.setDuration(200);

        upAnimation.setFillAfter(true);



        downAnimation = new RotateAnimation(-180, -360,

                Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,

                0.5f);

        downAnimation.setDuration(200);

        downAnimation.setFillAfter(true);

    }

    

    /**

     * 回调方法,用于刷新数据及加载更多

     * @param listener

     */

    public void setOnPullDownRefresh(OnPullDownRefresh listener) {

        this.mOnPullDownRefresh = listener;

    }



    public interface OnPullDownRefresh {

        public void onPullDownRefresh();

        public void onLoadingMore();

    }



    @Override

    public void onScrollStateChanged(AbsListView view, int scrollState) {

        if (!isEnabledLoadMore) {

            return;

        }

        //listView停止状态或惯性滑动状态

        if (scrollState == SCROLL_STATE_IDLE

                || scrollState == SCROLL_STATE_FLING) {

            //listView已到达最底部

            if ((getLastVisiblePosition() == getCount() - 1) && !isLoadingMore) {

                isLoadingMore = true;

                //展示脚布局

                //mFootView.setPadding(0, 0, 0, 0);

                setSelection(getCount());

                if (mOnPullDownRefresh != null) {

                    mOnPullDownRefresh.onLoadingMore();

                }

            }

        }

    }



    @Override

    public void onScroll(AbsListView view, int firstVisibleItem,

            int visibleItemCount, int totalItemCount) {

        

    }

    

    /**

     * 是否启用下拉刷新

     * @param isEnable

     */

    public void setEnabledPullDownRefresh(boolean isEnable) {

        isEnabledPullDownRefresh = isEnable;

    }

    

    /**

     * 是否启用加载更多

     * @param isEnable

     */

    public void setEnabledLoadMore(boolean isEnable) {

        isEnabledLoadMore = isEnable;

    }

}

 

 pull_listview_header.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

    android:layout_width="fill_parent"

    android:layout_height="wrap_content"

    android:orientation="vertical" >



    <LinearLayout

        android:id="@+id/ll_refresh_pull_down_header"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        android:orientation="horizontal" >



        <FrameLayout

            android:layout_width="40dp"

            android:layout_height="40dp"

            android:layout_marginBottom="3dp"

            android:layout_marginLeft="28dp"

            android:layout_marginTop="8dp" >



            <ImageView

                android:id="@+id/iv_refresh_header_arrow"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:layout_gravity="center"

                android:src="@drawable/common_listview_headview_red_arrow" />



            <ProgressBar

                android:id="@+id/pb_refresh_header"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:layout_gravity="center"

                android:indeterminateDrawable="@drawable/custom_progressbar"

                android:visibility="invisible" />

        </FrameLayout>



        <LinearLayout

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:layout_gravity="center_vertical"

            android:layout_weight="1"

            android:gravity="center_horizontal"

            android:orientation="vertical" >



            <TextView

                android:id="@+id/tv_refresh_header_status"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:text="下拉刷新"

                android:textColor="#ff0000"

                android:textSize="16sp"

                android:textStyle="bold" >

            </TextView>



            <TextView

                android:id="@+id/tv_refresh_header_time"

                android:layout_width="wrap_content"

                android:layout_height="wrap_content"

                android:layout_marginTop="5dp"

                android:text="最后刷新时间:09:23:23"

                android:textColor="@android:color/darker_gray"

                android:textSize="12sp" >

            </TextView>

        </LinearLayout>

        <TextView 

            android:layout_width="40dp"

            android:layout_marginRight="28dp"

            android:layout_height="wrap_content"

            />

    </LinearLayout>



</LinearLayout>

pull_listview_footer.xml

<?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:layout_width="40dp"

        android:layout_height="40dp"

        android:layout_margin="2dp"

        android:indeterminateDrawable="@drawable/custom_progressbar" />



    <TextView

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:gravity="center"

        android:padding="5dp"

        android:text="加载更多..."

        android:textColor="#ff0000"

        android:textSize="18sp" />



</LinearLayout>

custom_progressbar.xml

<?xml version="1.0" encoding="utf-8"?>

<rotate xmlns:android="http://schemas.android.com/apk/res/android"

    android:fromDegrees="0"

    android:pivotX="50%"

    android:pivotY="50%"

    android:toDegrees="360" >



    <shape

        android:innerRadiusRatio="4"

        android:shape="ring"

        android:thicknessRatio="10"

        android:useLevel="false" >

        <gradient

            android:centerColor="#ff6666"

            android:endColor="#ff0000"

            android:startColor="#ffffff"

            android:type="sweep" />

    </shape>



</rotate>

 

你可能感兴趣的:(ListView)