Public class MyListView extends ListView implements OnScrollListener {private static final String TAG = "listview"; private final static int RELEASE_To_REFRESH = 0; private final static int PULL_To_REFRESH = 1; private final static int REFRESHING = 2; private final static int DONE = 3; private final static int LOADING = 4; // RATIO of actual padding distance to interface offset private final static int RATIO = 3; private LayoutInflat Er inflater; private LinearLayout headView; private TextView tipsTextview; private TextView lastUpdatedTextView; private ImageView arrowImageView; private ProgressBar progressBar; private RotateAnimation animation; private vertex reverseAnimation; // ensure that the value of startY is recorded only once in a complete touch event. private int headContentWidth; private int headContentHeight; private int startY; private int FirstItemIndex; private int state; private boolean isBack; private OnRefreshListener refreshListener; private boolean isRefreshable; public MyListView (Context context) {super (context); init (context );} public MyListView (Context context, AttributeSet attrs) {super (context, attrs); init (context);} private void init (Context context) {// setCacheColorHint (context. getResources (). getColor (R. color. transparent); in Flater = LayoutInflater. from (context); headView = (LinearLayout) inflater. inflate (R. layout. head, null); arrowImageView = (ImageView) headView. findViewById (R. id. head_arrowImageView); arrowImageView. setMinimumWidth (70); arrowImageView. setMinimumHeight (50); progressBar = (ProgressBar) headView. findViewById (R. id. head_progressBar); tipsTextview = (TextView) headView. findViewById (R. id. head_tipsTextView); lastU PdatedTextView = (TextView) headView. findViewById (R. id. head_lastUpdatedTextView); measureView (headView); headContentHeight = headView. getMeasuredHeight (); headContentWidth = headView. getMeasuredWidth (); headView. setPadding (0,-1 * headContentHeight, 0, 0); headView. invalidate (); Log. v ("size", "width:" + headContentWidth + "height:" + headContentHeight); addHeaderView (headView, null, false); setOnScrollLi Stener (this); animation = new RotateAnimation (0,-180, RotateAnimation. RELATIVE_TO_SELF, 0.5f, RotateAnimation. RELATIVE_TO_SELF, 0.5f); animation. setInterpolator (new LinearInterpolator (); animation. setDuration (250); animation. setFillAfter (true); reverseAnimation = new RotateAnimation (-180, 0, RotateAnimation. RELATIVE_TO_SELF, 0.5f, RotateAnimation. RELATIVE_TO_SELF, 0.5f); reverseAnimation. setInterpolat Or (new LinearInterpolator (); reverseAnimation. setDuration (200); reverseAnimation. setFillAfter (true); state = DONE; isRefreshable = false;} public void onScroll (AbsListView arg0, int firstVisiableItem, int arg2, int arg3) {firstItemIndex = firstVisiableItem ;} public void onScrollStateChanged (AbsListView arg0, int arg1) {} public boolean onTouchEvent (MotionEvent event) {if (isRefreshable) {switch (event. g EtAction () {case MotionEvent. ACTION_DOWN: if (firstItemIndex = 0 &&! IsRecored) {isRecored = true; startY = (int) event. getY (); Log. v (TAG, "record current position when down '");} break; case MotionEvent. ACTION_UP: if (state! = REFRESHING & state! = LOADING) {if (state = DONE) {// nothing else} if (state = PULL_To_REFRESH) {state = DONE; changeHeaderViewByState (); Log. v (TAG, "Refresh from drop-down to done status");} if (state = RELEASE_To_REFRESH) {state = REFRESHING; changeHeaderViewByState (); onRefresh (); Log. v (TAG, "from release refresh status to done status") ;}} isRecored = false; isBack = false; break; case MotionEvent. ACTION_MOVE: int tempY = (int) event. getY (); if (! IsRecored & firstItemIndex = 0) {Log. v (TAG, "record location when moving"); isRecored = true; startY = tempY;} if (state! = REFRESHING & isRecored & state! = LOADING) {// ensure that the current position is always in the head during the padding setting process. Otherwise, if the list exceeds the screen, when pushing, the list will scroll at the same time. // you can easily refresh the if (state = RELEASE_To_REFRESH) {setSelection (0); // push up to the extent that the screen is sufficient to cover up the head, however, it has not been pushed to the full-covered level. if (tempY-startY)/RATIO
Layout file:
Head. xml:
<? Xml version = "1.0" encoding = "UTF-8"?> <! -- ListView header --> <LinearLayout xmlns: android = "http://schemas.android.com/apk/res/android" android: layout_width = "fill_parent" android: layout_height = "wrap_content" android: background = "# ffffff"> <! -- Content --> <RelativeLayout android: id = "@ + id/head_contentLayout" android: layout_width = "fill_parent" android: layout_height = "wrap_content" android: paddingLeft = "30dp"> <! -- Arrow image and progress bar --> <FrameLayout android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: Layout = "true" android: layout_centerVertical = "true"> <! -- Arrow --> <ImageView android: id = "@ + id/head_arrowImageView" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_gravity = "center" android: src = "@ drawable/arrow_down"/> <! -- Progress bar --> <ProgressBar android: id = "@ + id/head_progressBar" style = "? Android: attr/progressBarStyleSmall "android: layout_width =" wrap_content "android: layout_height =" wrap_content "android: layout_gravity =" center "android: visibility = "gone"/> </FrameLayout> <! -- Prompt, latest update --> <LinearLayout android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: layout_centerHorizontal = "true" android: gravity = "center_horizontal" android: orientation = "vertical"> <! -- Prompt --> <TextView android: id = "@ + id/head_tipsTextView" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: text = "pull-down refresh" android: textSize = "15dp"/> <! -- Latest update --> <TextView android: id = "@ + id/head_lastUpdatedTextView" android: layout_width = "wrap_content" android: layout_height = "wrap_content" android: text = "Last updated" android: textSize = "12dp"/> </LinearLayout> </RelativeLayout> </LinearLayout>
Use Demo:
Import Java. util. permission list; import android. app. activity; import android. OS. asynctask; import android. OS. bundle; import android. view. layoutinflater; import android. view. view; import android. view. viewgroup; import android. widget. baseadapter; import android. widget. textview; import cn.com. karl. list. mylistview. onrefreshlistener; public class mainactivity extends activity {private region list <string> data; private baseadapter adapter; Public void oncreate (bundle savedinstancestate) {super. oncreate (savedinstancestate); setcontentview (R. layout. main); Data = new vertex list <string> (); For (INT I = 0; I <10; I ++) {data. add (string. valueof (I);} final mylistview listview = (mylistview) findviewbyid (R. id. listview); adapter = new baseadapter () {public view getview (INT position, view convertview, viewgroup parent) {convertview = layoutinflater. from (getapplicationcontext ()). inflate (R. layout. item, null); textview = (textview) convertview. findviewbyid (R. id. textview_item); textview. settext (data. get (position); Return convertview;} public long getitemid (INT position) {return position;} public object getitem (INT position) {return data. get (position);} public int getcount () {return data. size () ;}}; listview. setadapter (adapter); listview. setonrefreshlistener (New onrefreshlistener () {public void onrefresh () {New asynctask <void, void, void> () {protected void doinbackground (void... params) {try {thread. sleep (1000);} catch (exception e) {e. printstacktrace ();} data. addfirst ("refreshed content"); return NULL ;}@ overrideprotected void onpostexecute (void result) implements cute (null );}});}}
Demo layout file:
Main. xml:
<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <uk.ac.essex.MyListView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/listView" /> </LinearLayout>
Item. xml:
<?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="center_vertical" android:background="#ffffff" android:orientation="horizontal" > <ImageView android:id="@+id/imageView_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:src="@drawable/ic_launcher" /> <TextView android:id="@+id/textView_item" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="TextView" /></LinearLayout>