• 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 = 1; 
    
        private static final int PULL_TO_REFRESH = 2; 
    
        private static final int RELEASE_TO_REFRESH = 3; 
    
        private static final int REFRESHING = 4; 
    
         
    
        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(0,-180, 
    
                    RotateAnimation.RELATIVE_TO_SELF,0.5f, 
    
                    RotateAnimation.RELATIVE_TO_SELF,0.5f); 
    
            mFlipAnimation.setInterpolator(new LinearInterpolator()); 
    
            mFlipAnimation.setDuration(250); 
    
            mFlipAnimation.setFillAfter(true); 
    
            mReverseFlipAnimation = new RotateAnimation(-180,0, 
    
                    RotateAnimation.RELATIVE_TO_SELF,0.5f, 
    
                    RotateAnimation.RELATIVE_TO_SELF,0.5f); 
    
            mReverseFlipAnimation.setInterpolator(new LinearInterpolator()); 
    
            mReverseFlipAnimation.setDuration(250); 
    
            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(50); 
    
             
    
            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(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); 
    
            } 
    
            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(1); 
    
        } 
    
     
    
        @Override 
    
        public void setAdapter(ListAdapter adapter) {  
    
            super.setAdapter(adapter); 
    
            setSelection(1); 
    
        } 
    
     
    
        @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() == 0 && mRefreshState != REFRESHING) { 
    
                        if ((mRefreshView.getBottom() > mRefreshViewHeight 
    
                                || mRefreshView.getTop() >= 0) 
    
                                && mRefreshState == RELEASE_TO_REFRESH) { 
    
                            // Initiate the refresh 
    
                            mRefreshState = REFRESHING; 
    
                            prepareForRefresh(); 
    
                            onRefresh(); 
    
                        } else if (mRefreshView.getBottom() < mRefreshViewHeight 
    
                                || mRefreshView.getTop() < 0) { 
    
                            // Abort refresh and scroll down below the refresh view 
    
                            resetHeader(); 
    
                            setSelection(1); 
    
                        } 
    
                    } 
    
                    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 = 1; 
    
            try { 
    
                Method method = MotionEvent.class.getMethod("getPointerCount"); 
    
                pointerCount = (Integer)method.invoke(ev); 
    
            } catch (NoSuchMethodException e) { 
    
                pointerCount = 1; 
    
            } catch (IllegalArgumentException e) { 
    
                throw e; 
    
            } catch (IllegalAccessException e) { 
    
                System.err.println("unexpected " + e); 
    
            } catch (InvocationTargetException e) { 
    
                System.err.println("unexpected " + e); 
    
            } 
    
     
    
            for (int h = 0; h < historySize; h++) { 
    
                for (int p = 0; p < pointerCount; p++) { 
    
                    if (mRefreshState == RELEASE_TO_REFRESH) { 
    
                        if (isVerticalFadingEdgeEnabled()) { 
    
                            setVerticalScrollBarEnabled(false); 
    
                        } 
    
     
    
                        int historicalY = 0; 
    
                        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 == 0) { 
    
                    mRefreshViewImage.setVisibility(View.VISIBLE); 
    
                    if((mRefreshView.getBottom() > mRefreshViewHeight + 20 
    
                            || mRefreshView.getTop() >= 0) 
    
                            && 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 + 20){ 
    
                        mRefreshViewImage.setVisibility(View.GONE); 
    
                        resetHeader(); 
    
                    }else if(mRefreshView.getBottom() == mRefreshViewHeight  
    
                            && mRefreshState == TAP_TO_REFRESH){ 
    
                        //不作为 
    
                        mRefreshViewImage.setVisibility(View.GONE); 
    
                        resetHeader(); 
    
                    } else if(mRefreshView.getBottom() < mRefreshViewHeight + 20 
    
                            && 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 == 0 
    
                    && mRefreshState != REFRESHING) { 
    
                setSelection(1); 
    
            } 
    
     
    
            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() > 0) { 
    
                invalidateViews(); 
    
                setSelection(1); 
    
            } 
    
        } 
    
    } 

    使用时:

    expLV.setOnRefreshListener(new OnRefreshListener(){ 
    
                @Override 
    
                public void onRefresh() { 
    
                    //远程取数据机制 
    
            });   
  • 相关阅读:
    Moq4在.NET3.5和.NET4版本之间的差异
    TDD中的迭代
    洛谷 3413 萌数
    割点(tarjan)
    hdu-4507 吉哥系列故事——恨7不成妻
    hdu-3709 Balanced Number
    poj-3252 Round Numbers
    hdu 1007 Quoit Design 分治求最近点对
    LA 3905 Meteor 扫描线
    uva 11464
  • 原文地址:https://www.cnblogs.com/zhujiabin/p/6101785.html
Copyright © 2020-2023  润新知