Android UI 之 下拉刷新和上拉加载

来源:互联网 发布:网络布线验收报告 编辑:程序博客网 时间:2024/05/20 04:14

前言:

下拉刷新和上拉加载,在很多应用中,我们都可以看到,其目的是为了通过刷新,分批次去加载一些数据量大的数据,

从而保证我们获取及显示在listView条目上及时,且又能保证获取的数据不会有遗漏,下面我们就来看一下下拉刷新和

上拉加载的特效是如何做的......


效果图:

                        


下拉刷新的步骤:

步骤一:添加一个头部到listView中,并将其隐藏

/*** * 添加一个刷新的头部到RefreshListView中来 * ***/headerView = View.inflate(getContext(),R.layout.header_layout,null);headerFreshText = (TextView) headerView.findViewById(R.id.headerFreshText);headerArrow = (ImageView) headerView.findViewById(R.id.headerArrow);headerProgress = (ProgressBar) headerView.findViewById(R.id.headerProgress);headerDateText = (TextView) headerView.findViewById(R.id.headerDateText);/*** * 因为系统在通过XML解析文件时,是需要一定时间的, * 所以当我们直接在构造函数中去通过getHeight()方式 * 去得到headerView的高度时,此时是为0的,只有当调用系统 * 调用onLayout()方法之后,headerView的高度才真正确定下来; * * 获取headerView高度的方式分为两种:方式一和方式二 * 可参考:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/0802/1641.html * **//*** * 通过调用onMeasure()方法,然后再配合getMeasureHeight()方法 * 去得到headerView的测量高度,但是这个高度有时不是最终的高度,因为在 * 整个布局中,其有时会受其余控件的影响,从而将其控件挤出了一部分, * 为了能让系统调用onMeasure()方法,可以通过headerView.measure(0,0), * 此时系统就会调用onMeasure()方法 * **/ headerView.measure(0,0); /***  * 在通过这种方法获得高度时,此时这里是用的getMeasuredHeight()方法;  * **/ headerViewHeight = headerView.getMeasuredHeight(); /***  * 通过设置TopPadding使headerView实现隐藏的效果;  * **/ headerView.setPadding(0,-headerViewHeight,0,0); /***  * 将头部添加到listView的上方;  * **/ addHeaderView(headerView);


步骤二:重写onTouchEvent(MotionEvent ev),根据不同的事件来切换不同的UI效果

/*** * 在示例中,这个事件的处理用在头部view上, * 关于底部的view并没有在这里进行处理; * ***/@Overridepublic boolean onTouchEvent(MotionEvent ev) {    switch (ev.getAction()){        /***         * 触摸屏幕时就记录下此时触摸的Y坐标值;         * ***/        case MotionEvent.ACTION_DOWN:            downY = (int) ev.getY();            break;        case MotionEvent.ACTION_MOVE:            /***             * 测出手指在屏幕的Y方向上移动的距离             * **/            distanceY = (int) (ev.getY() - downY);            /***             * (getFirstVisiblePosition() == 0):             * 只有当listView的第一行出现在头部时,此时去拉动,隐藏的头部才出现,             * (currentState != FRESHING_STATE):表示当正在刷新时,此时应该让下拉失效;             * 否则正在刷新时,手指再去滑动屏幕,会造成listView还会继续滑动的效果,这样给人的             * 效果就不好了;             * **/            if((distanceY > 0)&&(getFirstVisiblePosition() == 0)                    &&(currentState != FRESHING_STATE)){                if((distanceY < headerViewHeight)                        &&(currentState == RELEASE_FRESH_STATE)){                    /***                     * 由释放刷新转变为下拉刷新                     * **/                    currentState = PULL_FRESH_STATE;                    freshHeaderView();                } else if((distanceY >= headerViewHeight)                        &&(currentState == PULL_FRESH_STATE)){                    /***                     * 由下拉刷新转变为释放刷新                     * **/                    currentState = RELEASE_FRESH_STATE;                    freshHeaderView();                }                headerView.setPadding(0,-headerViewHeight + distanceY,0,0);                /***                 * 拦截事件,不允许listView去获得该事件,                 * 否则listView继续处理该事件时,会多滑动一段距离;                 * ***/                return true;            }            break;        case MotionEvent.ACTION_UP:            /****             * 如果滑动的距离小于headerViewHeight就松开了,             * 那么此时就立即以藏headerView;否则则让其进入正在刷新状态;             * **/            if(currentState == PULL_FRESH_STATE){                headerView.setPadding(0,-headerViewHeight,0,0);            }else if(currentState == RELEASE_FRESH_STATE){                currentState = FRESHING_STATE;                /***                 * 当正在刷新的时候,提供一个接口给用户,                 * 让其去实现正在刷新时的操作;                 * **/                if(freshListener != null){                    freshListener.onPullFresh();                }            }            freshHeaderView();            break;    }    return super.onTouchEvent(ev);}


步骤三:设置一个接口给用户,方便正在刷新时,用户去处理一些逻辑

/**** * 提供一个刷新侦听设置的接口给用户, * 用于在正在刷新时,进行一些数据的获取; * **/public void setOnFreshListener(OnFreshListener freshListener){    this.freshListener = freshListener;}/**** * 刷新侦听的接口,里边的onPullFresh()方法由用户去实现, * 这个方法里边主要是由用户来去实现上拉刷新的正在刷新时的逻辑; * **/public interface OnFreshListener{    /***     * 下拉刷新的正在刷新时,提供给用户去实现的方法,     * 主要是用来实现正在刷新时,用户需要实现的逻辑     * **/    void onPullFresh();    /***     * 上拉加载时,提供给用户去实现的方法,     * 主要是用来实现上拉加载时,用户需要实现的逻辑     * **/    void onLoadFresh();}


上拉加载的步骤:

步骤一:添加底部view到listView中,并将底部view隐藏

/*** * 添加底部view控件到listView的底部 * **/footView = View.inflate(getContext(),R.layout.foot_layout,null);/** * 得到footView的真实高度; * **/footView.measure(0,0);footViewHeight = footView.getMeasuredHeight();/*** * 通过设置TopPadding-footViewHeight实现隐藏; * ***/footView.setPadding(0,-footViewHeight,0,0);/*** * 将底部添加到listView上; * **/addFooterView(footView);


步骤二:设置滑动侦听,当滑动停止时,让底部view显示出来

/*** * scrollState有三种状态: * OnScrollListener.SCROLL_STATE_IDLE: * 滑动停止时的状态 * * OnScrollListener.SCROLL_STATE_TOUCH_SCROLL: * 手指正在屏幕滑动时的状态 * * OnScrollListener.SCROLL_STATE_FLING: * 手指离开屏幕,此时由于惯性继续滑动的状态; * * 当由一个状态变为另一个状态时,此时这个方法就会被调用; * * 注: * 记得对这个侦听进行设置,此时这个侦听才有效; * 否则光重写这个侦听,但没有对其进行侦听的设置, * 那么其是无法侦听得到的; * **/setOnScrollListener(new OnScrollListener() {    @Override    public void onScrollStateChanged(AbsListView view, int scrollState) {        switch (scrollState){            case OnScrollListener.SCROLL_STATE_IDLE:                Log.e("LastVisiblePosition","" + getLastVisiblePosition());                Log.e("count","" + getCount());                /***                 * getCount()最终调用的是适配器中的getCount()方法,                 * 所以在这里其实没有包括头部和尾部的view的,所以这个                 * 方法是成立的;                 * **/                if((getLastVisiblePosition() == getCount()-1)){                    /***                     * 让头部的整个高度显示出来,此时,还需向上再滑一下,                     * 才可以在屏幕上看到,所以后边用了setSelection(getCount())方法;                     * **/                    footView.setPadding(0,0,0,0);                    /***                     * 此时底部的view已经出现了,只是在屏幕之外,                     * 但需要再滑动一下listview才能在屏幕上看到,                     * 为了达到在一次滑动的过程中,让listView自动                     * 再滑动一下,此时就可以通过setSelection(getCount())                     * 来设置listView的那些条目显示在界面上,从而达到                     * 显示出底部view的效果;                     * **/                    setSelection(getCount());                    /****                     * 用于区分是上拉加载还是下拉刷新                     * **/                    isLoadingMore = true;                    /***                     * 当处于上拉加载时,此时调用用户实现的侦听接口的方法                     * **/                    if(freshListener != null){                        freshListener.onLoadFresh();                    }                }                break;            case OnScrollListener.SCROLL_STATE_TOUCH_SCROLL:                break;            case OnScrollListener.SCROLL_STATE_FLING:                break;        }    }    /***     * 当在滑动时,这个方法都会被调用,然而在这里并没卵用     * **/    @Override    public void onScroll(AbsListView view, int firstVisibleItem            , int visibleItemCount, int totalItemCount) {}});


步骤三:设置侦听接口给用户,当处于上拉加载状态时,让用户去处理自己的一些逻辑

/**** * 提供一个刷新侦听设置的接口给用户, * 用于在正在刷新时,进行一些数据的获取; * **/public void setOnFreshListener(OnFreshListener freshListener){    this.freshListener = freshListener;}/**** * 刷新侦听的接口,里边的onPullFresh()方法由用户去实现, * 这个方法里边主要是由用户来去实现上拉刷新的正在刷新时的逻辑; * **/public interface OnFreshListener{    /***     * 下拉刷新的正在刷新时,提供给用户去实现的方法,     * 主要是用来实现正在刷新时,用户需要实现的逻辑     * **/    void onPullFresh();    /***     * 上拉加载时,提供给用户去实现的方法,     * 主要是用来实现上拉加载时,用户需要实现的逻辑     * **/    void onLoadFresh();}


总结:

无论是下拉刷新还是上拉加载,都是通过setPadding(0,TopPadding,0,0)设置来达到各种不同的UI效果


源码:

点击源码即可下载~~~


0 0
原创粉丝点击