Android ExpandableListView的下拉刷新实现

该控件的修改时根据PullToRefreshList的机制修改

下面是对ExpandableListView的扩展

package com.up91.gwy.view.componet; 

import java.lang.reflect.InvocationTargetException; 

import java.lang.reflect.Method; 

import com.up91.gwy.R; 

import android.content.Context; 

import android.util.AttributeSet; 

import android.view.LayoutInflater; 

import android.view.MotionEvent; 

import android.view.View; 

import android.view.ViewGroup; 

import android.view.animation.LinearInterpolator; 

import android.view.animation.RotateAnimation; 

import android.widget.AbsListView; 

import android.widget.ExpandableListView; 

import android.widget.AbsListView.OnScrollListener; 

import android.widget.ImageView; 

import android.widget.ListAdapter; 

import android.widget.ProgressBar; 

import android.widget.RelativeLayout; 

import android.widget.TextView; 

public class PullToRefreshExpandableListView 

        extends ExpandableListView 

        implements 

            OnScrollListener { 

    private static final String TAG = "PullToRefreshExpandableListView"; 

    private static final int TAP_TO_REFRESH = ; 

    private static final int PULL_TO_REFRESH = ; 

    private static final int RELEASE_TO_REFRESH = ; 

    private static final int REFRESHING = ; 

    private OnRefreshListener mOnRefreshListener; 

    private OnScrollListener mOnScrollListener; 

    private LayoutInflater  mInflater; 

    private RelativeLayout  mRefreshView; 

    private TextView mRefreshViewText; 

    private ImageView mRefreshViewImage; 

    private ProgressBar mRefreshViewProgress; 

    private TextView   mRefreshViewLastUpdated; 

    private int mCurrentScrollState; 

    private int mRefreshState; 

    private RotateAnimation mFlipAnimation; 

    private RotateAnimation mReverseFlipAnimation; 

    private int mRefreshViewHeight; 

    private int mRefreshOriginalTopPadding; 

    private int mLastMotionY; 

    private boolean isInInitState; 

    public PullToRefreshExpandableListView(Context context) { 

        super(context); 

        init(context); 

    } 

    public PullToRefreshExpandableListView(Context context, AttributeSet attrs) { 

        super(context,attrs); 

        init(context); 

    } 

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

        super(context,attrs,defStyle); 

        init(context); 

    } 

    private void init(Context context){ 

        mFlipAnimation = new RotateAnimation(,-, 

                RotateAnimation.RELATIVE_TO_SELF,0.5f, 

                RotateAnimation.RELATIVE_TO_SELF,0.5f); 

        mFlipAnimation.setInterpolator(new LinearInterpolator()); 

        mFlipAnimation.setDuration(); 

        mFlipAnimation.setFillAfter(true); 

        mReverseFlipAnimation = new RotateAnimation(-,, 

                RotateAnimation.RELATIVE_TO_SELF,0.5f, 

                RotateAnimation.RELATIVE_TO_SELF,0.5f); 

        mReverseFlipAnimation.setInterpolator(new LinearInterpolator()); 

        mReverseFlipAnimation.setDuration(); 

        mReverseFlipAnimation.setFillAfter(true); 

        mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); 

        mRefreshView = (RelativeLayout) mInflater.inflate(R.layout.pull_to_refresh_header, this,false); 

        mRefreshViewText = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text); 

        mRefreshViewImage = (ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image); 

        mRefreshViewProgress = (ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress); 

        mRefreshViewLastUpdated = (TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at); 

        mRefreshViewImage.setMinimumHeight(); 

        mRefreshView.setOnClickListener(new OnClickRefreshListener()); 

        mRefreshOriginalTopPadding = mRefreshView.getPaddingTop(); 

        mRefreshState = TAP_TO_REFRESH; 

        addHeaderView(mRefreshView); 

        super.setOnScrollListener(this); 

        measureView(mRefreshView); 

        mRefreshViewHeight = mRefreshView.getMeasuredHeight(); 

    } 

    private void measureView(View child){ 

        ViewGroup.LayoutParams p = child.getLayoutParams(); 

        if(p == null){ 

            p = new ViewGroup.LayoutParams( 

                    ViewGroup.LayoutParams.FILL_PARENT, 

                    ViewGroup.LayoutParams.WRAP_CONTENT 

                ); 

        } 

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

        int lpHeight = p.height; 

        int childHeightSpec; 

        if(lpHeight > ){ 

            childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY); 

        }else{ 

            childHeightSpec = MeasureSpec.makeMeasureSpec(, MeasureSpec.UNSPECIFIED); 

        } 

        child.measure(childWidthSpec,childHeightSpec); 

    } 

    private class OnClickRefreshListener implements OnClickListener{ 

        @Override 

        public void onClick(View v) { 

            if(mRefreshState != REFRESHING){ 

                prepareForRefresh(); 

                onRefresh(); 

            } 

        } 

    } 

    public interface OnRefreshListener{ 

        public void onRefresh(); 

    } 

    @Override 

    protected void onAttachedToWindow() { 

        super.onAttachedToWindow(); 

        setSelection(); 

    } 

    @Override 

    public void setAdapter(ListAdapter adapter) {  

        super.setAdapter(adapter); 

        setSelection(); 

    } 

    @Override 

    public void setOnScrollListener(OnScrollListener l) { 

        mOnScrollListener = l; 

    } 

    public void setOnRefreshListener(OnRefreshListener onRefreshListener){ 

        mOnRefreshListener = onRefreshListener; 

    } 

    public void setLastUpdated(CharSequence lastUpdated){ 

        if(lastUpdated != null){ 

            mRefreshViewLastUpdated.setVisibility(View.VISIBLE); 

            mRefreshViewLastUpdated.setText(lastUpdated); 

        }else{ 

            mRefreshViewLastUpdated.setVisibility(View.GONE); 

        } 

    } 

    public boolean onTouchEvent(MotionEvent event) { 

        final int y = (int) event.getY(); 

        switch (event.getAction()) { 

            case MotionEvent.ACTION_UP: 

                if (!isVerticalScrollBarEnabled()) { 

                    setVerticalScrollBarEnabled(true); 

                } 

                if (getFirstVisiblePosition() ==  && mRefreshState != REFRESHING) { 

                    if ((mRefreshView.getBottom() > mRefreshViewHeight 

                            || mRefreshView.getTop() >= ) 

                            && mRefreshState == RELEASE_TO_REFRESH) { 

                        // Initiate the refresh 

                        mRefreshState = REFRESHING; 

                        prepareForRefresh(); 

                        onRefresh(); 

                    } else if (mRefreshView.getBottom() < mRefreshViewHeight 

                            || mRefreshView.getTop() < ) { 

                        // Abort refresh and scroll down below the refresh view 

                        resetHeader(); 

                        setSelection(); 

                    } 

                } 

                break; 

            case MotionEvent.ACTION_DOWN: 

                mLastMotionY = y; 

                break; 

            case MotionEvent.ACTION_MOVE: 

                applyHeaderPadding(event); 

                break; 

        } 

        return super.onTouchEvent(event); 

    } 

    private void applyHeaderPadding(MotionEvent ev) { 

        final int historySize = ev.getHistorySize(); 

        // Workaround for getPointerCount() which is unavailable in 1.5 

        // (it's always 1 in 1.5) 

        int pointerCount = ; 

        try { 

            Method method = MotionEvent.class.getMethod("getPointerCount"); 

            pointerCount = (Integer)method.invoke(ev); 

        } catch (NoSuchMethodException e) { 

            pointerCount = ; 

        } catch (IllegalArgumentException e) { 

            throw e; 

        } catch (IllegalAccessException e) { 

            System.err.println("unexpected " + e); 

        } catch (InvocationTargetException e) { 

            System.err.println("unexpected " + e); 

        } 

        for (int h = ; h < historySize; h++) { 

            for (int p = ; p < pointerCount; p++) { 

                if (mRefreshState == RELEASE_TO_REFRESH) { 

                    if (isVerticalFadingEdgeEnabled()) { 

                        setVerticalScrollBarEnabled(false); 

                    } 

                    int historicalY = ; 

                    try { 

                        // For Android > 2.0 

                        Method method = MotionEvent.class.getMethod( 

                                "getHistoricalY", Integer.TYPE, Integer.TYPE); 

                        historicalY = ((Float) method.invoke(ev, p, h)).intValue(); 

                    } catch (NoSuchMethodException e) { 

                        // For Android < 2.0 

                        historicalY = (int) (ev.getHistoricalY(h)); 

                    } catch (IllegalArgumentException e) { 

                        throw e; 

                    } catch (IllegalAccessException e) { 

                        System.err.println("unexpected " + e); 

                    } catch (InvocationTargetException e) { 

                        System.err.println("unexpected " + e); 

                    } 

                    // Calculate the padding to apply, we divide by 1.7 to 

                    // simulate a more resistant effect during pull. 

                    int topPadding = (int) (((historicalY - mLastMotionY) 

                            - mRefreshViewHeight) / 1.7); 

                    mRefreshView.setPadding( 

                            mRefreshView.getPaddingLeft(), 

                            topPadding, 

                            mRefreshView.getPaddingRight(), 

                            mRefreshView.getPaddingBottom()); 

                } 

            } 

        } 

    } 

    private void resetHeaderPadding() { 

        mRefreshView.setPadding( 

                mRefreshView.getPaddingLeft(), 

                mRefreshOriginalTopPadding, 

                mRefreshView.getPaddingRight(), 

                mRefreshView.getPaddingBottom()); 

    } 

    private void resetHeader() { 

        if (mRefreshState != TAP_TO_REFRESH) { 

            mRefreshState = TAP_TO_REFRESH; 

            resetHeaderPadding(); 

            // Set refresh view text to the pull label 

            mRefreshViewText.setText(R.string.pull_to_refresh_tap_label); 

            // Replace refresh drawable with arrow drawable 

            mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow); 

            // Clear the full rotation animation 

            mRefreshViewImage.clearAnimation(); 

            // Hide progress bar and arrow. 

            mRefreshViewImage.setVisibility(View.GONE); 

            mRefreshViewProgress.setVisibility(View.GONE); 

        } 

    } 

    public void onScroll(AbsListView view, int firstVisibleItem, 

            int visibleItemCount, int totalItemCount) { 

        // When the refresh view is completely visible, change the text to say 

        // "Release to refresh..." and flip the arrow drawable. 

        if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL 

                && mRefreshState != REFRESHING) { 

            if (firstVisibleItem == ) { 

                mRefreshViewImage.setVisibility(View.VISIBLE); 

                if((mRefreshView.getBottom() > mRefreshViewHeight +  

                        || mRefreshView.getTop() >= ) 

                        && mRefreshState == PULL_TO_REFRESH){ 

                    mRefreshViewText.setText(R.string.pull_to_refresh_release_label); 

                    mRefreshViewImage.clearAnimation(); 

                    mRefreshViewImage.startAnimation(mFlipAnimation); 

                    mRefreshState = RELEASE_TO_REFRESH; 

                }else if(mRefreshState == RELEASE_TO_REFRESH 

                        &&mRefreshView.getBottom() < mRefreshViewHeight + ){ 

                    mRefreshViewImage.setVisibility(View.GONE); 

                    resetHeader(); 

                }else if(mRefreshView.getBottom() == mRefreshViewHeight  

                        && mRefreshState == TAP_TO_REFRESH){ 

                    //不作为 

                    mRefreshViewImage.setVisibility(View.GONE); 

                    resetHeader(); 

                } else if(mRefreshView.getBottom() < mRefreshViewHeight +  

                        && mRefreshState == TAP_TO_REFRESH){ 

                    mRefreshViewText.setText(R.string.pull_to_refresh_pull_label); 

                    mRefreshState = PULL_TO_REFRESH; 

                    mRefreshViewImage.clearAnimation(); 

                    mRefreshViewImage.startAnimation(mReverseFlipAnimation); 

                } 

            } else { 

                mRefreshViewImage.setVisibility(View.GONE); 

                resetHeader(); 

            } 

        } else if (mCurrentScrollState == SCROLL_STATE_FLING 

                && firstVisibleItem ==  

                && mRefreshState != REFRESHING) { 

            setSelection(); 

        } 

        if (mOnScrollListener != null) { 

            mOnScrollListener.onScroll(view, firstVisibleItem, 

                    visibleItemCount, totalItemCount); 

        } 

    } 

    public void onScrollStateChanged(AbsListView view, int scrollState) { 

        mCurrentScrollState = scrollState; 

        if (mOnScrollListener != null) { 

            mOnScrollListener.onScrollStateChanged(view, scrollState); 

        } 

    } 

    public void prepareForRefresh() { 

        resetHeaderPadding(); 

        mRefreshViewImage.setVisibility(View.GONE); 

        // We need this hack, otherwise it will keep the previous drawable. 

        mRefreshViewImage.setImageDrawable(null); 

        mRefreshViewProgress.setVisibility(View.VISIBLE); 

        // Set refresh view text to the refreshing label 

        mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label); 

        mRefreshState = REFRESHING; 

    } 

    public void onRefresh() { 

        if (mOnRefreshListener != null) { 

            mOnRefreshListener.onRefresh(); 

            resetHeader(); 

        } 

    } 

    public void onRefreshComplete(CharSequence lastUpdated) { 

        setLastUpdated(lastUpdated); 

        onRefreshComplete(); 

    } 

    public void onRefreshComplete() {         

        resetHeader(); 

        // If refresh view is visible when loading completes, scroll down to 

        // the next item.  

        if (mRefreshView.getBottom() > ) { 

            invalidateViews(); 

            setSelection(); 

        } 

    } 

} 

使用时:

expLV.setOnRefreshListener(new OnRefreshListener(){ 

            @Override 

            public void onRefresh() { 

                //远程取数据机制 

        });   
上一篇:Chapter 1 First Sight——1


下一篇:有效提高win7电脑网速50倍