android 仿新浪微博的弹性滑动

弹性滑动已经不是什么新鲜的玩意,但是这种的小控件或者是样式,在工作中也会经常的用到,这里就将我的一个弹性滑动的demo 贴出来给大家作为一个备份。

代码如下:

首先实现一个自定义的view:

  1. package com.girl.show.view;  
  2.   
  3.   
  4. import com.girl.show.R;  
  5.   
  6. import android.content.Context;  
  7. import android.util.AttributeSet;  
  8. import android.util.Log;  
  9. import android.view.LayoutInflater;  
  10. import android.view.MotionEvent;  
  11. import android.view.View;  
  12. import android.view.ViewGroup;  
  13. import android.view.animation.LinearInterpolator;  
  14. import android.view.animation.RotateAnimation;  
  15. import android.widget.AbsListView;  
  16. import android.widget.ImageView;  
  17. import android.widget.ListAdapter;  
  18. import android.widget.ListView;  
  19. import android.widget.ProgressBar;  
  20. import android.widget.RelativeLayout;  
  21. import android.widget.TextView;  
  22. import android.widget.AbsListView.OnScrollListener;  
  23.   
  24. public class PullToRefreshListView extends ListView implements OnScrollListener {  
  25.   
  26.     private static final int TAP_TO_REFRESH = 1;  
  27.     private static final int PULL_TO_REFRESH = 2;  
  28.     private static final int RELEASE_TO_REFRESH = 3;  
  29.     private static final int REFRESHING = 4;  
  30.   
  31.     private static final String TAG = "PullToRefreshListView";  
  32.   
  33.     private OnRefreshListener mOnRefreshListener;  
  34.   
  35.     /** 
  36.      * Listener that will receive notifications every time the list scrolls. 
  37.      */  
  38.     private OnScrollListener mOnScrollListener;  
  39.     private LayoutInflater mInflater;  
  40.   
  41.     private RelativeLayout mRefreshView;  
  42.     private TextView mRefreshViewText;  
  43.     private ImageView mRefreshViewImage;  
  44.     private ProgressBar mRefreshViewProgress;  
  45.     private TextView mRefreshViewLastUpdated;  
  46.   
  47.     private int mCurrentScrollState;  
  48.     private int mRefreshState;  
  49.   
  50.     private RotateAnimation mFlipAnimation;  
  51.     private RotateAnimation mReverseFlipAnimation;  
  52.   
  53.     private int mRefreshViewHeight;  
  54.     private int mRefreshOriginalTopPadding;  
  55.     private int mLastMotionY;  
  56.   
  57.     private boolean mBounceHack;  
  58.   
  59.     public PullToRefreshListView(Context context) {  
  60.         super(context);  
  61.         init(context);  
  62.     }  
  63.   
  64.     public PullToRefreshListView(Context context, AttributeSet attrs) {  
  65.         super(context, attrs);  
  66.         init(context);  
  67.     }  
  68.   
  69.     public PullToRefreshListView(Context context, AttributeSet attrs, int defStyle) {  
  70.         super(context, attrs, defStyle);  
  71.         init(context);  
  72.     }  
  73.   
  74.     private void init(Context context) {  
  75.         // Load all of the animations we need in code rather than through XML  
  76.         mFlipAnimation = new RotateAnimation(0, -180,RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
  77.         mFlipAnimation.setInterpolator(new LinearInterpolator());  
  78.         mFlipAnimation.setDuration(250);  
  79.         mFlipAnimation.setFillAfter(true);  
  80.         mReverseFlipAnimation = new RotateAnimation(-1800,RotateAnimation.RELATIVE_TO_SELF, 0.5f,RotateAnimation.RELATIVE_TO_SELF, 0.5f);  
  81.         mReverseFlipAnimation.setInterpolator(new LinearInterpolator());  
  82.         mReverseFlipAnimation.setDuration(250);  
  83.         mReverseFlipAnimation.setFillAfter(true);  
  84.         mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);  
  85.         mRefreshView = (RelativeLayout) mInflater.inflate(R.layout.pull_to_refresh_header, thisfalse);  
  86.         mRefreshViewText =(TextView) mRefreshView.findViewById(R.id.pull_to_refresh_text);  
  87.         mRefreshViewImage =(ImageView) mRefreshView.findViewById(R.id.pull_to_refresh_image);  
  88.         mRefreshViewProgress =(ProgressBar) mRefreshView.findViewById(R.id.pull_to_refresh_progress);  
  89.         mRefreshViewLastUpdated =(TextView) mRefreshView.findViewById(R.id.pull_to_refresh_updated_at);  
  90.         mRefreshViewImage.setMinimumHeight(50);  
  91.         mRefreshView.setOnClickListener(new OnClickRefreshListener());  
  92.         mRefreshOriginalTopPadding = mRefreshView.getPaddingTop();  
  93.   
  94.         mRefreshState = TAP_TO_REFRESH;  
  95.   
  96.         addHeaderView(mRefreshView);  
  97.   
  98.         super.setOnScrollListener(this);  
  99.   
  100.         measureView(mRefreshView);  
  101.         mRefreshViewHeight = mRefreshView.getMeasuredHeight();  
  102.     }  
  103.   
  104.     @Override  
  105.     protected void onAttachedToWindow() {  
  106.         setSelection(1);  
  107.     }  
  108.   
  109.     @Override  
  110.     public void setAdapter(ListAdapter adapter) {  
  111.         super.setAdapter(adapter);  
  112.   
  113.         setSelection(1);  
  114.     }  
  115.   
  116.     /** 
  117.      * Set the listener that will receive notifications every time the list 
  118.      * scrolls. 
  119.      *  
  120.      * @param l The scroll listener.  
  121.      */  
  122.     @Override  
  123.     public void setOnScrollListener(AbsListView.OnScrollListener l) {  
  124.         mOnScrollListener = l;  
  125.     }  
  126.   
  127.     /** 
  128.      * Register a callback to be invoked when this list should be refreshed. 
  129.      *  
  130.      * @param onRefreshListener The callback to run. 
  131.      */  
  132.     public void setOnRefreshListener(OnRefreshListener onRefreshListener) {  
  133.         mOnRefreshListener = onRefreshListener;  
  134.     }  
  135.   
  136.     /** 
  137.      * Set a text to represent when the list was last updated.  
  138.      * @param lastUpdated Last updated at. 
  139.      */  
  140.     public void setLastUpdated(CharSequence lastUpdated) {  
  141.         if (lastUpdated != null) {  
  142.             mRefreshViewLastUpdated.setVisibility(View.VISIBLE);  
  143.             mRefreshViewLastUpdated.setText(lastUpdated);  
  144.         } else {  
  145.             mRefreshViewLastUpdated.setVisibility(View.GONE);  
  146.         }  
  147.     }  
  148.   
  149.     @Override  
  150.     public boolean onTouchEvent(MotionEvent event) {  
  151.         final int y = (int) event.getY();  
  152.         mBounceHack = false;  
  153.   
  154.         switch (event.getAction()) {  
  155.             case MotionEvent.ACTION_UP:  
  156.                 if (!isVerticalScrollBarEnabled()) {  
  157.                     setVerticalScrollBarEnabled(true);  
  158.                 }  
  159.                 if (getFirstVisiblePosition() == 0 && mRefreshState != REFRESHING) {  
  160.                     if ((mRefreshView.getBottom() >= mRefreshViewHeight  
  161.                             || mRefreshView.getTop() >= 0)  
  162.                             && mRefreshState == RELEASE_TO_REFRESH) {  
  163.                         // Initiate the refresh  
  164.                         mRefreshState = REFRESHING;  
  165.                         prepareForRefresh();  
  166.                         onRefresh();  
  167.                     } else if (mRefreshView.getBottom() < mRefreshViewHeight  
  168.                             || mRefreshView.getTop() <= 0) {  
  169.                         // Abort refresh and scroll down below the refresh view  
  170.                         resetHeader();  
  171.                         setSelection(1);  
  172.                     }  
  173.                 }  
  174.                 break;  
  175.             case MotionEvent.ACTION_DOWN:  
  176.                 mLastMotionY = y;  
  177.                 break;  
  178.             case MotionEvent.ACTION_MOVE:  
  179.                 applyHeaderPadding(event);  
  180.                 break;  
  181.         }  
  182.         return super.onTouchEvent(event);  
  183.     }  
  184.   
  185.     private void applyHeaderPadding(MotionEvent ev) {  
  186.         // getHistorySize has been available since API 1  
  187.         int pointerCount = ev.getHistorySize();  
  188.   
  189.         for (int p = 0; p < pointerCount; p++) {  
  190.             if (mRefreshState == RELEASE_TO_REFRESH) {  
  191.                 if (isVerticalFadingEdgeEnabled()) {  
  192.                     setVerticalScrollBarEnabled(false);  
  193.                 }  
  194.   
  195.                 int historicalY = (int) ev.getHistoricalY(p);  
  196.   
  197.                 // Calculate the padding to apply, we divide by 1.7 to  
  198.                 // simulate a more resistant effect during pull.  
  199.                 int topPadding = (int) (((historicalY - mLastMotionY)  
  200.                         - mRefreshViewHeight) / 1.7);  
  201.   
  202.                 mRefreshView.setPadding(  
  203.                         mRefreshView.getPaddingLeft(),  
  204.                         topPadding,  
  205.                         mRefreshView.getPaddingRight(),  
  206.                         mRefreshView.getPaddingBottom());  
  207.             }  
  208.         }  
  209.     }  
  210.   
  211.     /** 
  212.      * Sets the header padding back to original size. 
  213.      */  
  214.     private void resetHeaderPadding() {  
  215.         mRefreshView.setPadding(  
  216.                 mRefreshView.getPaddingLeft(),  
  217.                 mRefreshOriginalTopPadding,  
  218.                 mRefreshView.getPaddingRight(),  
  219.                 mRefreshView.getPaddingBottom());  
  220.     }  
  221.   
  222.     /** 
  223.      * Resets the header to the original state. 
  224.      */  
  225.     private void resetHeader() {  
  226.         if (mRefreshState != TAP_TO_REFRESH) {  
  227.             mRefreshState = TAP_TO_REFRESH;  
  228.   
  229.             resetHeaderPadding();  
  230.   
  231.             // Set refresh view text to the pull label  
  232.             mRefreshViewText.setText(R.string.pull_to_refresh_tap_label);  
  233.             // Replace refresh drawable with arrow drawable  
  234.             mRefreshViewImage.setImageResource(R.drawable.ic_pulltorefresh_arrow);  
  235.             // Clear the full rotation animation  
  236.             mRefreshViewImage.clearAnimation();  
  237.             // Hide progress bar and arrow.  
  238.             mRefreshViewImage.setVisibility(View.GONE);  
  239.             mRefreshViewProgress.setVisibility(View.GONE);  
  240.         }  
  241.     }  
  242.   
  243.     private void measureView(View child) {  
  244.         ViewGroup.LayoutParams p = child.getLayoutParams();  
  245.         if (p == null) {  
  246.             p = new ViewGroup.LayoutParams(  
  247.                     ViewGroup.LayoutParams.FILL_PARENT,  
  248.                     ViewGroup.LayoutParams.WRAP_CONTENT);  
  249.         }  
  250.   
  251.         int childWidthSpec = ViewGroup.getChildMeasureSpec(0,  
  252.                 0 + 0, p.width);  
  253.         int lpHeight = p.height;  
  254.         int childHeightSpec;  
  255.         if (lpHeight > 0) {  
  256.             childHeightSpec = MeasureSpec.makeMeasureSpec(lpHeight, MeasureSpec.EXACTLY);  
  257.         } else {  
  258.             childHeightSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);  
  259.         }  
  260.         child.measure(childWidthSpec, childHeightSpec);  
  261.     }  
  262.   
  263.     @Override  
  264.     public void onScroll(AbsListView view, int firstVisibleItem,  
  265.             int visibleItemCount, int totalItemCount) {  
  266.         // When the refresh view is completely visible, change the text to say  
  267.         // "Release to refresh..." and flip the arrow drawable.  
  268.         if (mCurrentScrollState == SCROLL_STATE_TOUCH_SCROLL  
  269.                 && mRefreshState != REFRESHING) {  
  270.             if (firstVisibleItem == 0) {  
  271.                 mRefreshViewImage.setVisibility(View.VISIBLE);  
  272.                 if ((mRefreshView.getBottom() >= mRefreshViewHeight + 20  
  273.                         || mRefreshView.getTop() >= 0)  
  274.                         && mRefreshState != RELEASE_TO_REFRESH) {  
  275.                     mRefreshViewText.setText(R.string.pull_to_refresh_release_label);  
  276.                     mRefreshViewImage.clearAnimation();  
  277.                     mRefreshViewImage.startAnimation(mFlipAnimation);  
  278.                     mRefreshState = RELEASE_TO_REFRESH;  
  279.                 } else if (mRefreshView.getBottom() < mRefreshViewHeight + 20  
  280.                         && mRefreshState != PULL_TO_REFRESH) {  
  281.                     mRefreshViewText.setText(R.string.pull_to_refresh_pull_label);  
  282.                     if (mRefreshState != TAP_TO_REFRESH) {  
  283.                         mRefreshViewImage.clearAnimation();  
  284.                         mRefreshViewImage.startAnimation(mReverseFlipAnimation);  
  285.                     }  
  286.                     mRefreshState = PULL_TO_REFRESH;  
  287.                 }  
  288.             } else {  
  289.                 mRefreshViewImage.setVisibility(View.GONE);  
  290.                 resetHeader();  
  291.             }  
  292.         } else if (mCurrentScrollState == SCROLL_STATE_FLING  
  293.                 && firstVisibleItem == 0  
  294.                 && mRefreshState != REFRESHING) {  
  295.             setSelection(1);  
  296.             mBounceHack = true;  
  297.         } else if (mBounceHack && mCurrentScrollState == SCROLL_STATE_FLING) {  
  298.             setSelection(1);  
  299.         }  
  300.   
  301.         if (mOnScrollListener != null) {  
  302.             mOnScrollListener.onScroll(view, firstVisibleItem,  
  303.                     visibleItemCount, totalItemCount);  
  304.         }  
  305.     }  
  306.   
  307.     @Override  
  308.     public void onScrollStateChanged(AbsListView view, int scrollState) {  
  309.         mCurrentScrollState = scrollState;  
  310.   
  311.         if (mCurrentScrollState == SCROLL_STATE_IDLE) {  
  312.             mBounceHack = false;  
  313.         }  
  314.   
  315.         if (mOnScrollListener != null) {  
  316.             mOnScrollListener.onScrollStateChanged(view, scrollState);  
  317.         }  
  318.     }  
  319.   
  320.     public void prepareForRefresh() {  
  321.         resetHeaderPadding();  
  322.   
  323.         mRefreshViewImage.setVisibility(View.GONE);  
  324.         // We need this hack, otherwise it will keep the previous drawable.  
  325.         mRefreshViewImage.setImageDrawable(null);  
  326.         mRefreshViewProgress.setVisibility(View.VISIBLE);  
  327.   
  328.         // Set refresh view text to the refreshing label  
  329.         mRefreshViewText.setText(R.string.pull_to_refresh_refreshing_label);  
  330.   
  331.         mRefreshState = REFRESHING;  
  332.     }  
  333.   
  334.     public void onRefresh() {  
  335.         Log.d(TAG, "onRefresh");  
  336.   
  337.         if (mOnRefreshListener != null) {  
  338.             mOnRefreshListener.onRefresh();  
  339.         }  
  340.     }  
  341.   
  342.     /** 
  343.      * Resets the list to a normal state after a refresh. 
  344.      * @param lastUpdated Last updated at. 
  345.      */  
  346.     public void onRefreshComplete(CharSequence lastUpdated) {  
  347.         setLastUpdated(lastUpdated);  
  348.         onRefreshComplete();  
  349.     }  
  350.   
  351.     /** 
  352.      * Resets the list to a normal state after a refresh. 
  353.      */  
  354.     public void onRefreshComplete() {          
  355.         Log.d(TAG, "onRefreshComplete");  
  356.   
  357.         resetHeader();  
  358.   
  359.         // If refresh view is visible when loading completes, scroll down to  
  360.         // the next item.  
  361.         if (mRefreshView.getBottom() > 0) {  
  362.             invalidateViews();  
  363.             setSelection(1);  
  364.         }  
  365.     }  
  366.   
  367.     /** 
  368.      * Invoked when the refresh view is clicked on. This is mainly used when 
  369.      * there's only a few items in the list and it's not possible to drag the 
  370.      * list. 
  371.      */  
  372.     private class OnClickRefreshListener implements OnClickListener {  
  373.   
  374.         @Override  
  375.         public void onClick(View v) {  
  376.             if (mRefreshState != REFRESHING) {  
  377.                 prepareForRefresh();  
  378.                 onRefresh();  
  379.             }  
  380.         }  
  381.   
  382.     }  
  383.   
  384.     /** 
  385.      * Interface definition for a callback to be invoked when list should be 
  386.      * refreshed. 
  387.      */  
  388.     public interface OnRefreshListener {  
  389.         /** 
  390.          * Called when the list should be refreshed. 
  391.          * <p> 
  392.          * A call to {@link PullToRefreshListView #onRefreshComplete()} is 
  393.          * expected to indicate that the refresh has completed. 
  394.          */  
  395.         public void onRefresh();  
  396.     }  
  397. }  

  1. package com.girl.show.view;  
  2.   
  3. import android.content.Context;  
  4. import android.os.Build;  
  5. import android.util.Log;  
  6. import android.view.MotionEvent;  
  7. import android.view.ScaleGestureDetector;  
  8.   
  9. public abstract class VersionedGestureDetector {  
  10.     private static final String TAG = "VersionedGestureDetector";  
  11.       
  12.     OnGestureListener mListener;  
  13.       
  14.     public static VersionedGestureDetector newInstance(Context context,OnGestureListener listener) {  
  15.         final int sdkVersion = Integer.parseInt(Build.VERSION.SDK);  
  16.         VersionedGestureDetector detector = null;  
  17.         if (sdkVersion < Build.VERSION_CODES.ECLAIR) {  
  18.             detector = new CupcakeDetector();  
  19.         } else if (sdkVersion < Build.VERSION_CODES.FROYO) {  
  20.             detector = new EclairDetector();  
  21.         } else {  
  22.             detector = new FroyoDetector(context);  
  23.         }  
  24.           
  25.         Log.d(TAG, "Created new " + detector.getClass());  
  26.         detector.mListener = listener;  
  27.           
  28.         return detector;  
  29.     }  
  30.       
  31.     public abstract boolean onTouchEvent(MotionEvent ev);  
  32.       
  33.     public interface OnGestureListener {  
  34.         public void onDrag(float dx, float dy);  
  35.         public void onScale(float scaleFactor);  
  36.     }  
  37.   
  38.     private static class CupcakeDetector extends VersionedGestureDetector {  
  39.         float mLastTouchX;  
  40.         float mLastTouchY;  
  41.           
  42.         float getActiveX(MotionEvent ev) {  
  43.             return ev.getX();  
  44.         }  
  45.   
  46.         float getActiveY(MotionEvent ev) {  
  47.             return ev.getY();  
  48.         }  
  49.           
  50.         boolean shouldDrag() {  
  51.             return true;  
  52.         }  
  53.   
  54.         @Override  
  55.         public boolean onTouchEvent(MotionEvent ev) {  
  56.             switch (ev.getAction()) {  
  57.             case MotionEvent.ACTION_DOWN: {  
  58.                 mLastTouchX = getActiveX(ev);  
  59.                 mLastTouchY = getActiveY(ev);  
  60.                 break;  
  61.             }  
  62.             case MotionEvent.ACTION_MOVE: {  
  63.                 final float x = getActiveX(ev);  
  64.                 final float y = getActiveY(ev);  
  65.                   
  66.                 if (shouldDrag()) {  
  67.                     mListener.onDrag(x - mLastTouchX, y - mLastTouchY);  
  68.                 }  
  69.                   
  70.                 mLastTouchX = x;  
  71.                 mLastTouchY = y;  
  72.                 break;  
  73.             }  
  74.             }  
  75.             return true;  
  76.         }  
  77.     }  
  78.       
  79.     private static class EclairDetector extends CupcakeDetector {  
  80.         private static final int INVALID_POINTER_ID = -1;  
  81.         private int mActivePointerId = INVALID_POINTER_ID;  
  82.         private int mActivePointerIndex = 0;  
  83.   
  84.         @Override  
  85.         float getActiveX(MotionEvent ev) {  
  86.             return ev.getX(mActivePointerIndex);  
  87.         }  
  88.   
  89.         @Override  
  90.         float getActiveY(MotionEvent ev) {  
  91.             return ev.getY(mActivePointerIndex);  
  92.         }  
  93.   
  94.         @Override  
  95.         public boolean onTouchEvent(MotionEvent ev) {  
  96.             final int action = ev.getAction();  
  97.             switch (action & MotionEvent.ACTION_MASK) {  
  98.             case MotionEvent.ACTION_DOWN:  
  99.                 mActivePointerId = ev.getPointerId(0);  
  100.                 break;  
  101.             case MotionEvent.ACTION_CANCEL:  
  102.             case MotionEvent.ACTION_UP:  
  103.                 mActivePointerId = INVALID_POINTER_ID;  
  104.                 break;  
  105.             case MotionEvent.ACTION_POINTER_UP:  
  106.                 final int pointerIndex = (ev.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK)   
  107.                         >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;  
  108.                 final int pointerId = ev.getPointerId(pointerIndex);  
  109.                 if (pointerId == mActivePointerId) {  
  110.                     // This was our active pointer going up. Choose a new  
  111.                     // active pointer and adjust accordingly.  
  112.                     final int newPointerIndex = pointerIndex == 0 ? 1 : 0;  
  113.                     mActivePointerId = ev.getPointerId(newPointerIndex);  
  114.                     mLastTouchX = ev.getX(newPointerIndex);  
  115.                     mLastTouchY = ev.getY(newPointerIndex);  
  116.                 }  
  117.                 break;  
  118.             }  
  119.   
  120.             mActivePointerIndex = ev.findPointerIndex(mActivePointerId);  
  121.             return super.onTouchEvent(ev);  
  122.         }  
  123.     }  
  124.       
  125.     private static class FroyoDetector extends EclairDetector {  
  126.         private ScaleGestureDetector mDetector;  
  127.           
  128.         public FroyoDetector(Context context) {  
  129.             mDetector = new ScaleGestureDetector(context,  
  130.                     new ScaleGestureDetector.SimpleOnScaleGestureListener() {  
  131.                 @Override public boolean onScale(ScaleGestureDetector detector) {  
  132.                     mListener.onScale(detector.getScaleFactor());  
  133.                     return true;  
  134.                 }  
  135.             });  
  136.         }  
  137.           
  138.         @Override  
  139.         boolean shouldDrag() {  
  140.             return !mDetector.isInProgress();  
  141.         }  
  142.           
  143.         @Override  
  144.         public boolean onTouchEvent(MotionEvent ev) {  
  145.             mDetector.onTouchEvent(ev);  
  146.             return super.onTouchEvent(ev);  
  147.         }  
  148.     }  
  149. }  
实现完两个类之后实现xml:


  1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     android:layout_width="fill_parent"  
  3.     android:layout_height="fill_parent"  
  4.     android:paddingTop="10dip"  
  5.     android:paddingBottom="15dip"  
  6.     android:gravity="center"  
  7.     android:id="@+id/pull_to_refresh_header"  
  8.     >  
  9.     <ProgressBar   
  10.         android:id="@+id/pull_to_refresh_progress"  
  11.         android:indeterminate="true"  
  12.         android:layout_width="wrap_content"  
  13.         android:layout_height="wrap_content"  
  14.         android:layout_marginLeft="30dip"  
  15.         android:layout_marginRight="20dip"  
  16.         android:layout_marginTop="10dip"  
  17.         android:visibility="gone"  
  18.         android:layout_centerVertical="true"  
  19.         style="?android:attr/progressBarStyleSmall"  
  20.         />  
  21.     <ImageView  
  22.         android:id="@+id/pull_to_refresh_image"  
  23.         android:layout_width="wrap_content"  
  24.         android:layout_height="wrap_content"  
  25.         android:layout_marginLeft="30dip"  
  26.         android:layout_marginRight="20dip"  
  27.         android:visibility="gone"  
  28.         android:layout_gravity="center"  
  29.         android:gravity="center"  
  30.         android:src="@drawable/ic_pulltorefresh_arrow"  
  31.         />  
  32.     <TextView  
  33.         android:id="@+id/pull_to_refresh_text"  
  34.         android:text="@string/pull_to_refresh_tap_label"  
  35.         android:textAppearance="?android:attr/textAppearanceMedium"  
  36.         android:textStyle="bold"  
  37.         android:paddingTop="5dip"  
  38.         android:layout_width="fill_parent"  
  39.         android:layout_height="wrap_content"  
  40.         android:layout_gravity="center"  
  41.         android:gravity="center"  
  42.         />  
  43.     <TextView  
  44.         android:id="@+id/pull_to_refresh_updated_at"  
  45.         android:layout_below="@+id/pull_to_refresh_text"  
  46.         android:visibility="gone"  
  47.         android:textAppearance="?android:attr/textAppearanceSmall"  
  48.         android:layout_width="fill_parent"  
  49.         android:layout_height="wrap_content"  
  50.         android:layout_gravity="center"  
  51.         android:gravity="center"  
  52.         />  
  53. </RelativeLayout>  

  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="fill_parent"  
  5.     android:layout_height="fill_parent"  
  6.     android:background="@drawable/main_bg"  
  7.     >  
  8.     <!-- 
  9.     The PullToRefreshListView replaces a standard ListView widget. 
  10.     -->  
  11.     <com.girl.show.view.PullToRefreshListView  
  12.         android:id="@+id/android:list"  
  13.         android:layout_height="fill_parent"  
  14.         android:layout_width="fill_parent"  
  15.         android:cacheColorHint="#00000000"  
  16.         />  
  17. </LinearLayout>  
实现activity
  1. package com.girl.show.activity;  
  2.   
  3. import java.util.Arrays;  
  4. import java.util.LinkedList;  
  5.   
  6. import android.app.ListActivity;  
  7. import android.os.AsyncTask;  
  8. import android.os.Bundle;  
  9. import android.util.Log;  
  10. import android.widget.ArrayAdapter;  
  11.   
  12. import com.girl.show.R;  
  13. import com.girl.show.view.PullToRefreshListView;  
  14. import com.girl.show.view.PullToRefreshListView.OnRefreshListener;  
  15.   
  16. public class PullToRefreshActivity extends ListActivity {      
  17.     private LinkedList<String> mListItems;  
  18.     private static final String TAG="PullToRefreshActivity";  
  19.     /** Called when the activity is first created. */  
  20.     @Override  
  21.     public void onCreate(Bundle savedInstanceState) {  
  22.         super.onCreate(savedInstanceState);  
  23.         setContentView(R.layout.pull_to_refresh);  
  24.   
  25.         // Set a listener to be invoked when the list should be refreshed.  
  26.         ((PullToRefreshListView) getListView()).setOnRefreshListener(new OnRefreshListener() {  
  27.             @Override  
  28.             public void onRefresh() {  
  29.                 new GetDataTask().execute();  
  30.             }  
  31.         });  
  32.   
  33.         mListItems = new LinkedList<String>();  
  34.         mListItems.addAll(Arrays.asList(mStrings));  
  35.           
  36.         ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, mListItems);  
  37.           
  38.         setListAdapter(adapter);  
  39.           
  40.     }  
  41.   
  42.     private class GetDataTask extends AsyncTask<Void, Void, String[]> {  
  43.   
  44.         @Override  
  45.         protected String[] doInBackground(Void... params) {  
  46.             try {  
  47.                 Thread.sleep(2000);  
  48.             } catch (InterruptedException e) {  
  49.                 Log.d(TAG,"",e);  
  50.             }  
  51.             return mStrings;  
  52.         }  
  53.   
  54.         @Override  
  55.         protected void onPostExecute(String[] result) {  
  56.             mListItems.addFirst("Added after refresh...");  
  57.             ((PullToRefreshListView) getListView()).onRefreshComplete();  
  58.             super.onPostExecute(result);  
  59.         }  
  60.     }  
  61.   
  62.     private String[] mStrings = {  
  63.             "Abbaye de Belloc""Abbaye du Mont des Cats""Abertam",  
  64.             "Abondance""Ackawi""Acorn""Adelost""Affidelice au Chablis",  
  65.             "Afuega'l Pitu""Airag""Airedale""Aisy Cendre",  
  66.             "Allgauer Emmentaler"};  

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值