ListView实现下拉刷新

来源:互联网 发布:淘宝9.9包邮网 编辑:程序博客网 时间:2024/05/17 01:25

APP中是listview布局的界面一般都会有下拉刷新这个功能,很多三方的框架已经实现了,这儿是一个下拉刷新的基本实现。
主要模块:
1.listview中存在addHeaderView(View v)方法,该方法就是在listview头部添加一个自定义的view。(下拉刷新界面就是写在该内容当中)
2.下拉刷新分为下拉中,刷新中,没有下拉三个过程,处理好各个过程的关系。
3.下拉和刷新过程中的view的动画处理。
下面就是下拉刷新的实现代码:

首先自定义刷新界面的布局代码
refresh_head.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:orientation="horizontal" >    <FrameLayout         android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:paddingLeft="10dp"        android:paddingRight="10dp"        android:paddingTop="10dp"        android:paddingBottom="10dp"        >        <!-- 下拉刷新箭头 -->         <ImageView             android:id="@+id/iv_arr"            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_progress"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_gravity="center"            android:indeterminateDrawable="@drawable/custom_progress"            android:visibility="invisible"/>    </FrameLayout>    <LinearLayout         android:padding="10dp"        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:orientation="vertical"        android:layout_weight="1"        android:gravity="center"        >         <!-- 刷新的界面的文字 -->        <TextView             android:id="@+id/tv_title"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:textColor="#f00"            android:textSize="16sp"            android:text="下拉刷新"/>        <TextView             android:id="@+id/tv_time"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:textColor="@android:color/darker_gray"            android:textSize="14sp"            android:layout_marginTop="5dp"            android:text="最后刷新时间:2015-03-10 17:20"/>    </LinearLayout></LinearLayout>

自定义RefreshListView类继承listview

package view;import com.lzz.zhihuibeijing.R;import android.content.Context;import android.text.StaticLayout;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.ImageView;import android.widget.ListView;import android.widget.ProgressBar;import android.widget.TextView;/** * 下拉刷新的listview * @author lizezheng * */public class RefreshListView extends ListView {    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 = 1;//当前状态的状态码,默认是松开刷新的    private int starty = -1;//下拉刷新起始位置默认-1    private View mHeaderView;//下拉界面view    private int mHeaderViewHeight;// 下拉界面的高度    private TextView tvTitle;    private TextView tvTime;    private ImageView ivArrow;    private ProgressBar pbProgress;    private RotateAnimation animUp;//箭头上指的动画    private RotateAnimation animDown;//箭头下指的动画    //实现构造函数    public RefreshListView(Context context) {        super(context);        initHeaderView();//调用初始化方法    }    public RefreshListView(Context context, AttributeSet attrs) {        super(context, attrs);        initHeaderView();    }    public RefreshListView(Context context, AttributeSet attrs, int defStyle) {        super(context, attrs, defStyle);        initHeaderView();    }    /**     * 初始化头布局     */    private void initHeaderView() {        //将下拉界面的布局加载到view当中        mHeaderView = View.inflate(getContext(), R.layout.refresh_head, null);        //将View设置为listview的头部        this.addHeaderView(mHeaderView);        //获取布局当中的所有控件        tvTitle = (TextView) mHeaderView.findViewById(R.id.tv_title);        tvTime = (TextView) mHeaderView.findViewById(R.id.tv_time);        ivArrow = (ImageView) mHeaderView.findViewById(R.id.iv_arr);        pbProgress = (ProgressBar) mHeaderView.findViewById(R.id.pb_progress);        //测量布局的长宽高度,并获取下拉刷新界面的高度        mHeaderView.measure(0, 0);        mHeaderViewHeight = mHeaderView.getMeasuredHeight();        //将下拉刷新界面放到listview界面上方,因为只有我们手像下拉屏幕才会出现刷新界面        mHeaderView.setPadding(0, - mHeaderViewHeight, 0, 0);//隐藏头布局        //初始化动画效果        initArrowAnim();    }    //监听屏幕滑动状况    @Override    public boolean onTouchEvent(MotionEvent ev) {        switch (ev.getAction()) {        //触摸屏幕时        case MotionEvent.ACTION_DOWN:            //计算触摸屏幕时手指的Y坐标            starty  = (int) ev.getRawY();            break;            //滑动屏幕时        case MotionEvent.ACTION_MOVE:            //正在刷新时,不做处理            if(mCurrentState == STATE_REFRESHING){                break;            }            //如果初始Y坐标没有获取到就重新获取一次            if(starty == -1){                starty  = (int) ev.getRawY();            }            //获取当前手指的Y坐标            int endy = (int) ev.getRawY();            //计算出偏移量            int dy = endy - starty;//移动偏移量            //只有下拉并且当前是第一个item,才允许下拉刷新            if(dy > 0 && getFirstVisiblePosition() == 0){                //计算padding,即下拉的高度是否超过下拉刷新界面的高度                int padding = dy - mHeaderViewHeight;                //动态改变下拉刷新界面的出现百分比                mHeaderView.setPadding(0, padding, 0, 0);//设置padding                //如果下拉高度超过界面高度,状态改为松开刷新                if(padding > 0 && mCurrentState != STATE_RELEASE_REFRESH){                    mCurrentState = STATE_RELEASE_REFRESH;                    //调用函数                    refreshState();                //刚开始默认是松开刷新状态,所以这里如果下拉高度不够,更换状态,为上面的IF语句做准备                }else if(padding < 0 && mCurrentState != STATE_PULL_REFRESH){                    //改为下拉状态                    mCurrentState = STATE_PULL_REFRESH;                    refreshState();                }                return true;            }            break;            //手指离开屏幕        case MotionEvent.ACTION_UP:            //设置初始Y坐标            starty = -1;            //如果状态是松开刷新状态(表明下拉高度超过)则开始刷新,并更换状态            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;        default:            break;        }        return false;    }    /**     * 刷新下拉控件的布局     * 根据状态码来控制下拉界面的动画     */    private void refreshState() {        switch (mCurrentState) {        //下拉状态        case STATE_PULL_REFRESH:            tvTitle.setText("下拉刷新");            //箭头设置可见            ivArrow.setVisibility(View.VISIBLE);            //转动圆圈设置可见            pbProgress.setVisibility(View.INVISIBLE);            //箭头执行下拉动画            ivArrow.startAnimation(animDown);            break;        case STATE_RELEASE_REFRESH:            tvTitle.setText("松开刷新");            ivArrow.setVisibility(View.VISIBLE);            pbProgress.setVisibility(View.INVISIBLE);            ivArrow.startAnimation(animUp);            break;        case STATE_REFRESHING:            tvTitle.setText("正在刷新");            ivArrow.clearAnimation();//必须先清除动画才能隐藏            ivArrow.setVisibility(View.INVISIBLE);            pbProgress.setVisibility(View.VISIBLE);    break;        default:            break;        }    }    /**     * 箭头动画     */    private void initArrowAnim(){        //箭头 向上的动画        animUp = new RotateAnimation(0, -180,Animation.RELATIVE_TO_SELF,                0.5f,Animation.RELATIVE_TO_SELF,0.5f);        //设置动画时间        animUp.setDuration(200);        //设置动画是否保留最终状态        animUp.setFillAfter(true);        //箭头 向下的动画        animDown = new RotateAnimation(-180, 0,Animation.RELATIVE_TO_SELF,                0.5f,Animation.RELATIVE_TO_SELF,0.5f);        animDown.setDuration(200);        animDown.setFillAfter(true);    }}

刷新当中并没有做什么事情,只是改变了布局的动画,具体的刷新数据可以自行根据自身情况在refreshState()函数当中处理,但是注意新开线程~

0 0