ListView下拉刷新及上拉加载更多

①、定义HeaderView

package com.exi.oa.activity.widget.list;

import com.exi.oa.R;

import android.content.Context;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

public class HeaderView extends LinearLayout{
    
    /*定义HeaderView状态*/
    public final static int STATE_NORMAL = 0;
    public final static int STATE_WILL_RELEASE = 1;
    public final static int STATE_REFRESHING = 2;
    private int defaultState = STATE_NORMAL;
    
    /*定义HeaderView需要的组件*/
    private View headerView = null;
    private ImageView ivArrow = null;
    private ProgressBar pBar = null;
    private TextView refreshTips = null;
    
    /*定义滑动动画*/
    private RotateAnimation upRa = null;
    private RotateAnimation downRa = null;
    private final static int ROTATE_DURATION = 250;
    
    public HeaderView(Context context){
        this(context,null);
    }
    
    public HeaderView(Context context, AttributeSet attrs){
        super(context, attrs);
        initHeaderView(context);
    }
    
    /*初始化HeaderView*/
    private void initHeaderView(Context context){
        LinearLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0);
        headerView = LayoutInflater.from(context).inflate(R.layout.refresh_header, null);
        addView(headerView,lp);
        setGravity(Gravity.BOTTOM);
        
        ivArrow = (ImageView)findViewById(R.id.ivArrow);
        pBar = (ProgressBar)findViewById(R.id.pbWaiting);
        refreshTips = (TextView)findViewById(R.id.refresh_tips);
        
        upRa = new RotateAnimation(0.0f, -180.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        upRa.setDuration(ROTATE_DURATION);
        upRa.setFillAfter(true);
        
        downRa = new RotateAnimation(-180.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        downRa.setDuration(ROTATE_DURATION);
        downRa.setFillAfter(true);
    }
    
    /*设置HeaderView状态*/
    public void setHeaderState(int state){
        if(defaultState == state){
            return;
        }
        
        ivArrow.clearAnimation();
        if(state == STATE_REFRESHING){
            pBar.setVisibility(View.VISIBLE);
            ivArrow.setVisibility(View.GONE);
        }else{
            pBar.setVisibility(View.GONE);
            ivArrow.setVisibility(View.VISIBLE);
        }
        
        switch (state) {
        case STATE_NORMAL:
            ivArrow.startAnimation(downRa);
            refreshTips.setText(R.string.pull_down_for_refresh);
            break;
            
        case STATE_WILL_RELEASE:
            ivArrow.startAnimation(upRa);
            refreshTips.setText(R.string.release_for_refresh);
            break;
            
        case STATE_REFRESHING:
            refreshTips.setText(R.string.refreshing);
            break;

        default:
            break;
        }
        
        defaultState = state;
    }
    
    public int getCurrentState(){
        return defaultState;
    }
    
    public void setHeaderHeight(int height){
        if(height <= 0){
            height = 0;
        }
        LayoutParams lp = (LayoutParams)headerView.getLayoutParams();
        lp.height = height;
        headerView.setLayoutParams(lp);
    }
    
    public int getHeaderHeight(){
        return headerView.getHeight();
    }
    
}

  

HeaderView布局代码

<?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:background="#ffffff"
    android:gravity="bottom">
    
    <RelativeLayout 
        android:id="@+id/header_content"
        android:layout_width="match_parent"
        android:layout_height="60dip">
        
        <LinearLayout 
            android:id="@+id/layoutTitle"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:gravity="center"
            android:orientation="vertical">
            
            <TextView 
                android:id="@+id/refresh_tips"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:textSize="15sp"
                android:text="@string/pull_down_for_refresh"/>
            
            <LinearLayout 
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:orientation="horizontal"
                android:layout_marginTop="4dip">
                
                <TextView 
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="12sp"
                    android:text="@string/label_update"/>
                <TextView 
                    android:id="@+id/refresh_last_time"
                    android:layout_width="wrap_content"
                    android:layout_height="wrap_content"
                    android:textSize="12sp"
                    android:text="@string/label_last_time"/>
                
            </LinearLayout>
            
        </LinearLayout>
        
        <ImageView 
            android:id="@+id/ivArrow"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_toLeftOf="@id/layoutTitle"
            android:layout_centerInParent="true"
            android:layout_marginRight="30dip"
            android:contentDescription="@string/image_desc"
            android:src="@drawable/refresh_arrow_down"/>
        
        <ProgressBar 
            android:id="@+id/pbWaiting"
            android:visibility="gone"
            android:layout_height="wrap_content"
            android:layout_width="wrap_content"
            android:layout_toLeftOf="@id/layoutTitle"
            android:layout_centerInParent="true"
            android:layout_marginRight="30dip"
            style="?android:attr/progressBarStyleSmall"/>

    </RelativeLayout>

</LinearLayout>


②、定义FooterView

package com.exi.oa.activity.widget.list;

import com.exi.oa.R;

import android.content.Context;
import android.util.AttributeSet;
import android.view.LayoutInflater;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.RotateAnimation;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;

public class FooterView extends LinearLayout{
    
    /*定义FooterView显示项*/
    public final static int FOOTER_OPTIONS_PULL = 0;
    public final static int FOOTER_OPTIONS_CLICK = 1;
    private static int defaultOptions = FOOTER_OPTIONS_CLICK;
    
    /*定义FooterView状态*/
    public final static int STATE_NORMAL = 0;
    public final static int STATE_WILL_RESEALE = 1;
    public final static int STATE_LOADING = 2;
    private static int defaultState = STATE_NORMAL;
    
    /*定义FooterView需要的组件*/
    private View footerView = null;
    private ImageView ivArrow = null;
    private ProgressBar pBar = null;
    private TextView loaderTips = null;
    
    /*定义上下拉动画*/
    private RotateAnimation upRa = null;
    private RotateAnimation downRa = null;
    private final static int ROTATE_DURATION = 250;

    public FooterView(Context context) {
        this(context,null);
    }
    
    public FooterView(Context context,AttributeSet atts){
        super(context,atts);
        initFooterView(context);
    }
    
    /*初始化视图*/
    private void initFooterView(Context context){
        LinearLayout.LayoutParams lp = new LayoutParams(LayoutParams.MATCH_PARENT, 0);
        footerView = LayoutInflater.from(context).inflate(R.layout.loader_footer, null);
        this.addView(footerView,lp);
        
        ivArrow = (ImageView)footerView.findViewById(R.id.ivLoaderArrow);
        pBar = (ProgressBar)footerView.findViewById(R.id.pbLoaderWaiting);
        loaderTips = (TextView)footerView.findViewById(R.id.loader_tips);
        
        downRa = new RotateAnimation(0.0f, 180.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        downRa.setDuration(ROTATE_DURATION);
        downRa.setFillAfter(true);
        
        upRa = new RotateAnimation(180.0f, 0.0f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
        upRa.setDuration(ROTATE_DURATION);
        upRa.setFillAfter(true);
        
        setFooterViewOptions(FOOTER_OPTIONS_CLICK);
    }
    
    /*设置footerView项*/
    public void setFooterViewOptions(int options){
        defaultOptions = options;
        
        switch (defaultOptions) {
        case FOOTER_OPTIONS_PULL:
            hide();
            break;
            
        case FOOTER_OPTIONS_CLICK:
            show();
            break;

        default:
            break;
        }
    }
    
    /*获取footerView的项*/
    public int getFooterViewOptions(){
        return defaultOptions;
    }
    
    /*设置footerview状态*/
    public void setFooterSate(int state){
        if(this.defaultState == state){
            return;
        }
        
        ivArrow.clearAnimation();
        if(state == STATE_LOADING){
            pBar.setVisibility(View.VISIBLE);
            ivArrow.setVisibility(View.GONE);
        }else{
            pBar.setVisibility(View.GONE);
            ivArrow.setVisibility(View.VISIBLE);
        }
        
        switch (state) {
        case STATE_NORMAL:
            ivArrow.startAnimation(upRa);
            loaderTips.setText(R.string.pull_up_for_more);
            break;
            
        case STATE_WILL_RESEALE:
            ivArrow.startAnimation(downRa);
            loaderTips.setText(R.string.release_for_more);
            break;
            
        case STATE_LOADING:
            loaderTips.setText(R.string.loading);
            break;

        default:
            break;
        }
        defaultState = state;
    }
    
    /*获取footerView当前状态*/
    public int getCurrentState(){
        return defaultState;
    }
    
    /*设置footerView的高度*/
    public void setFooterHeight(int height){
        if(height <= 0){
            height = 0;
        }
        
        LayoutParams lp = (LayoutParams)footerView.getLayoutParams();
        lp.height = height;
        footerView.setLayoutParams(lp);
    }
    
    /*获取footerView的高度*/
    public int getFooterHeight(){
        return footerView.getHeight();
    }
    
    /*隐藏*/
    public void hide(){
        ivArrow.clearAnimation();
        ivArrow.setVisibility(View.VISIBLE);
        loaderTips.setText(R.string.pull_up_for_more);
        setFooterHeight(0);
    }
    
    /*显示*/
    public void show(){
        ivArrow.clearAnimation();
        ivArrow.setVisibility(View.GONE);
        loaderTips.setText(R.string.click_for_more);
        
        LayoutParams lp = (LayoutParams)footerView.getLayoutParams();
        lp.height = LayoutParams.WRAP_CONTENT;
        footerView.setLayoutParams(lp);
    }
}


FooterView布局文件

<?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="top"
    android:background="#ffffff" >

    <RelativeLayout
        android:id="@+id/footer_content"
        android:layout_width="match_parent"
        android:layout_height="60dip" >

        <TextView
            android:id="@+id/loader_tips"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="@string/pull_up_for_more"
            android:textSize="15sp" />

        <ImageView
            android:id="@+id/ivLoaderArrow"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_marginRight="30dip"
            android:layout_toLeftOf="@id/loader_tips"
            android:contentDescription="@string/image_desc"
            android:src="@drawable/refresh_arrow_up" />

        <ProgressBar
            android:id="@+id/pbLoaderWaiting"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:layout_marginRight="30dip"
            android:layout_toLeftOf="@id/loader_tips"
            android:visibility="gone" />
    </RelativeLayout>

</LinearLayout>


③、定义ListView

package com.exi.oa.activity.widget.list;

import com.exi.oa.R;

import android.content.Context;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.view.animation.DecelerateInterpolator;
import android.widget.AbsListView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Scroller;
import android.widget.AbsListView.OnScrollListener;

public class TaskListView extends ListView implements OnScrollListener{
    
    /*定义HeaderView*/
    private HeaderView headerView = null;
    private RelativeLayout headerContent = null;
    private int headerHeight = 0;
    
    /*定义FooterView*/
    private FooterView footerView = null;
    private RelativeLayout footerContent = null;
    private int footerHeight = 0;
    
    private final static int SCROLL_HEADER = 0;
    private final static int SCROLL_FOOTER = 1;
    private int defaultScrollWhich = SCROLL_FOOTER;
    
    private Scroller scroller = null;
    private final static float OFFSET_Y = 0.7F;
    private float iLastY = 0;
    private int totalNumber = 0;
    
    private OnLoaderListener loaderListener;

    public TaskListView(Context context) {
        this(context, null, 0);
    }
    
    public TaskListView(Context context,AttributeSet attrs){
        this(context, attrs, 0);
    }
    
    public TaskListView(Context context,AttributeSet attrs,int defStyle){
        super(context,attrs,defStyle);
        initView(context);
    }
    
    private void initView(Context context){
        scroller = new Scroller(context, new DecelerateInterpolator());
        super.setOnScrollListener(this);
        
        initFooterView(context);
        //initHeaderView(context);
    }
    
    /*重写设置适配器方法*/
    @Override
    public void setAdapter(ListAdapter adapter) {
        if(getFooterViewsCount() == 0){
            addFooterView(footerView);
        }
        super.setAdapter(adapter);
    }
    
    /*重写触屏事件的回调方法*/
    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        switch (ev.getAction()) {
        
        case MotionEvent.ACTION_DOWN:   //当屏幕被按下时
            iLastY = ev.getY();
            break;
            
        case MotionEvent.ACTION_MOVE:   //当在屏幕中滑动时
            float deltaY = ev.getY() - iLastY;
            iLastY = ev.getY();
            /*if(canHeaderPull() && getFirstVisiblePosition() == 0
                    && (deltaY > 0 || headerView.getHeaderHeight() > 0)){
                updateHeaderState(deltaY * OFFSET_Y);
            }else if(canFooterPull() && getLastVisiblePosition() == totalNumber - 1
                    && (deltaY < 0 || footerView.getFooterHeight() > 0)){
                updateFooterState(-deltaY * OFFSET_Y);
            }*/
            if(canFooterPull() && getLastVisiblePosition() == totalNumber - 1
                    && (deltaY < 0 || footerView.getFooterHeight() > 0)){
                updateFooterState(-deltaY * OFFSET_Y);
            }
            break;
            
        case MotionEvent.ACTION_UP:   //当屏幕被抬起时、也就是手指离开屏幕是
            /*if(getFirstVisiblePosition() == 0){
                if(headerView.getHeaderHeight() > headerHeight){
                    headerView.setHeaderState(HeaderView.STATE_REFRESHING);
                    if(footerView.getFooterViewOptions() == FooterView.FOOTER_OPTIONS_CLICK){
                        footerView.hide();
                    }
                }
                resetHeader();
            }else if(getLastVisiblePosition() == totalNumber - 1){
                if(footerView.getFooterHeight() > footerHeight){
                    footerView.setFooterSate(FooterView.STATE_LOADING);
                }
                resetFooter();
            }*/
            if(getLastVisiblePosition() == totalNumber - 1){
                if(footerView.getFooterHeight() > footerHeight){
                    footerView.setFooterSate(FooterView.STATE_LOADING);
                    loader();
                }
                resetFooter();
            }
            break;

        default:
            break;
        }
        return super.onTouchEvent(ev);
    }
    
    @Override
    public void computeScroll() {
        if(scroller.computeScrollOffset()){
            /*if(defaultScrollWhich == SCROLL_HEADER){
                headerView.setHeaderHeight(scroller.getCurrY());
            }else */
            if(defaultScrollWhich == SCROLL_FOOTER){
                footerView.setFooterHeight(scroller.getCurrY());
            }
        }
        super.computeScroll();
    }
    
    /*
     * 滑动时获取ListView有多少个item
     * 1. 在init中,需要设置super.setOnScrollListener;
     * 2. 重载以下两个函数;
     * 3. 在onScroll中取得totalItemCount即可;
     * */
    @Override
    public void onScroll(AbsListView view, int firstVisibleItem,
            int visibleItemCount, int totalItemCount) {
        //滑动时触发该方法
        totalNumber = totalItemCount;
    }

    @Override
    public void onScrollStateChanged(AbsListView view, int scrollState) {
        //滑动改变时触发该方法
    }
    
    public void setOnLoaderListener(OnLoaderListener listener){
        this.loaderListener = listener;
    }
    
    public void loader(){
        if(this.loaderListener != null){
            loaderListener.onLoader();
        }
    }
    
    /*========================================================================================*/
    private boolean canHeaderPull(){
        if(footerView.getCurrentState() == FooterView.STATE_NORMAL){
            return true;
        }
        return false;
    }
    
    public boolean canFooterPull(){
        //if(headerView.getCurrentState() == HeaderView.STATE_NORMAL){
            return true;
        //}
        //return false;
    }

    /*==================================================Footer=================================================*/
    /*返回FooterView*/
    public FooterView getFooterView(){
        return footerView;
    }
    
    /*设置Footer模型*/
    public void setFooterMode(int options){
        footerView.setFooterViewOptions(options);
    }
    
    /*停止加载*/
    public void stopLoad(){
        if(footerView.getCurrentState() == FooterView.STATE_LOADING){
            footerView.setFooterSate(FooterView.STATE_NORMAL);
            resetFooter();
        }
    }
    
    /*初始化footerView*/
    private void initFooterView(Context context){
        footerView = new FooterView(context);
        footerContent = (RelativeLayout)footerView.findViewById(R.id.footer_content);
        footerContent.setOnClickListener(new OnClickListener() {
            
            @Override
            public void onClick(View v) {
                if(footerView.getFooterViewOptions() == FooterView.FOOTER_OPTIONS_CLICK
                        && footerView.getCurrentState() == FooterView.STATE_NORMAL){
                    footerView.setFooterSate(FooterView.STATE_LOADING);
                    loader();
                }
            }
        });
        footerView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            
            @Override
            public void onGlobalLayout() {
                footerHeight = footerContent.getHeight();
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
    }
    
    /*更新FooterView状态*/
    private void updateFooterState(float delta){
        if(footerView.getFooterViewOptions() == FooterView.FOOTER_OPTIONS_CLICK){
            return;
        }
        
        footerView.setFooterHeight((int)(delta+footerView.getFooterHeight()));
        if(footerView.getCurrentState() != FooterView.STATE_LOADING){
            if(footerView.getFooterHeight() > footerHeight){
                footerView.setFooterSate(FooterView.STATE_WILL_RESEALE);
            }else{
                footerView.setFooterSate(FooterView.STATE_NORMAL);
            }
        }
    }
    
    /*重置Footer*/
    private void resetFooter(){
        int height = footerView.getFooterHeight();
        if(height == 0){
            return;
        }
        
        if(footerView.getFooterViewOptions() == FooterView.FOOTER_OPTIONS_CLICK){
            return;
        }
        
        int finalHeight = 0;
        if(height > footerHeight){
            finalHeight = footerHeight;
        }else if(footerView.getCurrentState() == FooterView.STATE_LOADING){
            return;
        }
        
        defaultScrollWhich = SCROLL_FOOTER;
        scroller.startScroll(0, height, finalHeight - height, 250);
        invalidate();
    }
    
    /*==========================================Header==========================================================*/
    /*返回HeaderView
    public HeaderView getHeaderView(){
        return headerView;
    }
    停止刷新
    public void stopRefresh(){
        if(headerView.getCurrentState() == HeaderView.STATE_REFRESHING){
            headerView.setHeaderState(HeaderView.STATE_NORMAL);
            resetHeader();
            if(footerView.getFooterViewOptions() == FooterView.FOOTER_OPTIONS_CLICK){
                footerView.show();
            }
        }
    }
    
    初始化HeaderView
    private void initHeaderView(Context context){
        headerView = new HeaderView(context);
        headerContent = (RelativeLayout)headerView.findViewById(R.id.header_content);
        addHeaderView(headerView);
        headerView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
            
            @Override
            public void onGlobalLayout() {
                headerHeight = headerContent.getHeight();
                getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        });
    }
    
    更新Headerview状态
    private void updateHeaderState(float delta){
        headerView.setHeaderHeight((int)(delta + headerView.getHeaderHeight()));
        if(headerView.getCurrentState() != HeaderView.STATE_REFRESHING){
            if(headerView.getHeaderHeight() > headerHeight){
                headerView.setHeaderState(HeaderView.STATE_WILL_RELEASE);
            }else{
                headerView.setHeaderState(HeaderView.STATE_NORMAL);
            }
        }
        setSelection(0);
    }
    
    重置Header
    private void resetHeader(){
        int height = headerView.getHeaderHeight();
        if(height == 0){
            return;
        }
        int finalHeight = 0;
        if(height > headerHeight){
            
             * 如果超过HeaderView高度,则回滚到HeaderView高度即可
             
            finalHeight = headerHeight;
        }else if(headerView.getCurrentState() == HeaderView.STATE_REFRESHING){
            
             * 如果HeaderView未完全显示
             * 1. 处于正在刷新中,则不管;
             * 2. 回滚HeaderView当前可视高度
             
            return;
        }
        
        defaultScrollWhich = SCROLL_HEADER;
        scroller.startScroll(0, height, 0, finalHeight, 250);
        invalidate();
    }
*/
    
    private class OnClickLoaderListener implements OnClickListener{

        @Override
        public void onClick(View v) {
            loader();
        }
        
    }
    
    public interface OnLoaderListener{
        
        public void onLoader();
        
    }
}


在ListView中定义OnLoaderListener接口作为加载数据监听器、加载数据只需实现此监听器即可

 

posted @ 2013-11-25 10:47  Yang2  阅读(553)  评论(0编辑  收藏  举报