为自己记------android中listview下拉刷新和下拉加载的原理及简单实现

来源:互联网 发布:莆田电视台 网络直播 编辑:程序博客网 时间:2024/05/28 03:01

自定义listview,实现下拉刷新功能和上拉加载功能

1.下拉刷新

实现原理:通过onTouchEvent判断手势,来改变listview的header。

header的状态共4种,自己定义为:none, normal, willrefresh, refreshing ,header在四种状态切换时不仅改变内部组件,同时改变自身的大小。

footer类似


实现:


import android.content.Context;


import android.os.Handler;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AbsListView.OnScrollListener;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;


import com.windlu.anywhere.R;




/**
 * 自定义的listview,实现上拉刷新和下拉加载
 * @author lufeng
 *
 */
public class PushAndDownListview extends ListView implements OnScrollListener{

private StateBar headView;//头部view

private StateBar footerView;//脚部view

private int headerContentHeight;//头部view的高度

private int footerContentHeight;//脚部view的高度

private static final int Refresh = 0;//刷新

private static final int Load = 1;//加载

private int    Operating=-1;//操作


private PushAndDownListviewRefreshOrLoad mPushAndDownListviewRefreshOrLoad;//加载或刷新的回调接口


public PushAndDownListview(Context context) {
this(context,null);
}
public PushAndDownListview(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}


private void init(Context context){

//头部
headView = new StateBar(context);

headView.setStatusStrings(getResources().getString(R.string.pull_to_refresh), 
getResources().getString(R.string.release_to_refresh), 
getResources().getString(R.string.refreshing));


//测量view的高度
measureView(headView);

headerContentHeight=headView.getMeasuredHeight();

//设置view的toppadding值
headtopPadding(-headerContentHeight);
//添加view
addHeaderView(headView);

//脚部
footerView = new StateBar(context);
footerView.setStatusStrings(getResources().getString(R.string.pull_up_load), 
getResources().getString(R.string.release_to_load), 
getResources().getString(R.string.loading));

measureView(footerView);

footerContentHeight = footerView.getMeasuredHeight();

footerTopPadding(-footerContentHeight);

addFooterView(footerView);

}



float startY;

boolean isRecordedStartY;//是否已经记录StartY

int firstVisibleItemPosition ;
int LastVisibleItemPosition;
int totalItemCounts;

private boolean isRefreshing;

//主要在该方法中实现下拉刷新效果和上拉加载效果
@Override
public boolean onTouchEvent(MotionEvent ev) {
switch (ev.getAction()) {  
       case MotionEvent.ACTION_DOWN:
        if((firstVisibleItemPosition==0 || LastVisibleItemPosition==totalItemCounts) && Operating == -1&&!isRefreshing){
        startY = ev.getY();
        isRecordedStartY=true;
        return true;
        }
           break;  
       case MotionEvent.ACTION_UP: 
        isRecordedStartY=false;
        if((firstVisibleItemPosition==0 || LastVisibleItemPosition==totalItemCounts) && Operating != -1&&!isRefreshing){
        if(Operating == Refresh){
        if(headView.getStateType()==StateType.willrefresh){
        headView.setRefreshStatus(StateType.refreshing);
        headtopPadding(0);
        doRefreshWork();
        }else if(headView.getStateType()==StateType.refreshing){
        }else{
        RefreshWorkComplete();
//         Operating=-1;
//         headView.setRefreshStatus(StateType.none);
//         headtopPadding(-headerContentHeight);
        }
        }else if(Operating == Load){
        if(footerView.getStateType()==StateType.willrefresh){
        footerView.setRefreshStatus(StateType.refreshing);
        footerTopPadding(0);
        doLoadWork();
        }else if(footerView.getStateType()==StateType.refreshing){
        }else{
        LoadWorkComplete();
//         Operating=-1;
//         footerView.setRefreshStatus(StateType.none);
//         footerTopPadding(-footerContentHeight);
        }
        }
        }
        break;  
       case MotionEvent.ACTION_MOVE:
        if((firstVisibleItemPosition==0 || LastVisibleItemPosition==totalItemCounts)&&!isRefreshing){
        whenMove(ev);
        }
        break;
       default:  
           break;  
       }  
return super.onTouchEvent(ev);
}


private void doRefreshWork() {
isRefreshing =  true;
if(mPushAndDownListviewRefreshOrLoad!=null){
mPushAndDownListviewRefreshOrLoad.Refresh();
}else{
new Handler().postDelayed(new Runnable() {
public void run() {
RefreshWorkComplete();
}
}, 3000);
}
}

private void doLoadWork() {
isRefreshing =  true;
if(mPushAndDownListviewRefreshOrLoad!=null){
mPushAndDownListviewRefreshOrLoad.Load();
}else{
new Handler().postDelayed(new Runnable() {
public void run() {
LoadWorkComplete();
}
}, 3000);
}
}

//设置监听
public void setPushAndDownListviewRefreshOrLoadListener(PushAndDownListviewRefreshOrLoad listener){
this.mPushAndDownListviewRefreshOrLoad = listener;
}

//刷新完成后调用
public void RefreshWorkComplete(){
isRefreshing =  false;
Operating=-1;
headView.setRefreshStatus(StateType.none);
headtopPadding(-headerContentHeight);
}

//加载完成后调用
public void LoadWorkComplete(){
isRefreshing = false;
Operating = -1;
footerView.setRefreshStatus(StateType.none);
footerTopPadding(-footerContentHeight);
}

private void whenMove(MotionEvent ev){
if(!isRecordedStartY || headView.getStateType()==StateType.refreshing || footerView.getStateType()==StateType.refreshing){
return;
}

float stempY = ev.getY();
int distanceY = (int)(stempY - startY);
if(distanceY > 0 && firstVisibleItemPosition == 0){
//执行刷新状态
doRefresh(distanceY);
}else if(distanceY < 0 && LastVisibleItemPosition==totalItemCounts){
//执行加载状态
doLoad(distanceY);
}
}

private void doRefresh(int distanceY){
Operating = Refresh;
if(distanceY-headerContentHeight < 0){
headView.setRefreshStatus(StateType.normal);
}else if(distanceY-headerContentHeight >= 0){
headView.setRefreshStatus(StateType.willrefresh);
}
headtopPadding(distanceY-headerContentHeight);
}


private void doLoad(int distanceY){
Operating = Load;
if(-(distanceY+footerContentHeight) < 0){
footerView.setRefreshStatus(StateType.normal);
}else if(-(distanceY+footerContentHeight) >= 0){
footerView.setRefreshStatus(StateType.willrefresh);
}
footerTopPadding(-(distanceY+footerContentHeight));
}

/**
* 测量view的方法
* @param view必须使用线性布局
*/
private void measureView(View clild) {

ViewGroup.LayoutParams p = clild.getLayoutParams();//获取layoutparams
if (p == null) {
p = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
}

int childWidthSpec = ViewGroup.getChildMeasureSpec(0, 0 + 0, p.width);//宽

int lpHeight = p.height;

int childHeightSpec;

if (lpHeight > 0) {
childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight,MeasureSpec.EXACTLY);
} else {
childHeightSpec = MeasureSpec.makeMeasureSpec(0,MeasureSpec.UNSPECIFIED);
}

clild.measure(childWidthSpec, childHeightSpec);//measure(0,0)必须使用线性布局,否则报空指针异常,因为线性布局重写了该方法,其他没有从写
}

/**
* 为headview从新设置padding
* @param topPadding
*/
private void headtopPadding(int topPadding) {
headView.setPadding(headView.getPaddingLeft(), topPadding,headView.getPaddingRight(), headView.getPaddingBottom());
headView.invalidate();
}

private void footerTopPadding(int topPadding){
footerView.setPadding(footerView.getPaddingLeft(), topPadding,footerView.getPaddingRight(), footerView.getPaddingBottom());
footerView.invalidate();
}



@Override
public void onScrollStateChanged(AbsListView view, int scrollState) {
}


@Override
public void onScroll(AbsListView view, int firstVisibleItem,
int visibleItemCount, int totalItemCount) {
this.firstVisibleItemPosition = firstVisibleItem;
this.LastVisibleItemPosition  = firstVisibleItem+visibleItemCount;
this.totalItemCounts=totalItemCount;
}


//状态
enum StateType{
none, normal, willrefresh, refreshing 
}
//自定义的状态显示view,用于添加到listview的头部和脚部
class StateBar extends LinearLayout{
//状态
StateType mStateType = StateType.none;
//显示的文字
private String normalString;  
        private String willrefreshString;  
        private String refreshingString; 

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



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




//ui控件
ProgressBar progressBar;
TextView    tv_state;
TextView    tv_updatetime;

private void init(Context context){
LayoutInflater.from(context).inflate(R.layout.view_listviewheadorfoot, this);

progressBar = (ProgressBar) findViewById(R.id.progressBar);
tv_state = (TextView) findViewById(R.id.tv_state);
tv_updatetime = (TextView) findViewById(R.id.tv_updatetime);
//设置状态
setRefreshStatus(mStateType);
}

//设置view的当前状态
public void setRefreshStatus(StateType refreshStatus) {  
            if (this.mStateType != refreshStatus) {  
                this.mStateType = refreshStatus;  
                if(mStateType == StateType.refreshing){  
                    this.progressBar.setVisibility(View.VISIBLE);  
                }else{  
                    this.progressBar.setVisibility(View.GONE);  
                }  
                refreshStatusString();  
                this.invalidate();  
            }  
        }

//刷新状态文字
private void refreshStatusString() {
            switch (mStateType) {
            case none:
            case normal:  
            tv_state.setText(normalString);  
                break;  
            case willrefresh:  
            tv_state.setText(willrefreshString);  
                break;  
            case refreshing:  
            tv_state.setText(refreshingString);  
                break;  
            default:  
                break;  
            }
            //这里先不做时间设置
            tv_updatetime.setText("");
        } 

public StateType getStateType(){
return mStateType;
}
public void setStatusStrings(String normalString, String willrefreshString, String refreshingString){  
            this.normalString = normalString;  
            this.willrefreshString = willrefreshString;  
            this.refreshingString = refreshingString;  
            this.refreshStatusString();  
        }  

}

interface  PushAndDownListviewRefreshOrLoad{
void Refresh();
void Load();
}
}


有待完善。。。。。。

0 0
原创粉丝点击