Android custom control (5) pull-down refresh of Sina Weibo, android Sina

Source: Internet
Author: User

Android custom control (5) pull-down refresh of Sina Weibo, android Sina

There are many well-known open-source frameworks on the Internet. Here we will pull the PullToRefresh framework, which is the pull-down refresh we use at ordinary times. Of course, what are the usage of this framework? Others have already written this article. Here we mainly focus on learning and practice. When the number of exercises is too large, everything will go with the flow.

To put it bluntly, first, go to the Code:

1. To implement the pull-down refresh function, you must have a pull-down refresh layout, right?

<?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="match_parent"    android:orientation="vertical" >        <RelativeLayout        android:layout_width="match_parent"        android:layout_height="wrap_content"        android:paddingBottom="10dip"        android:paddingTop="10dip" >        <LinearLayout            android:id="@+id/layout"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_centerInParent="true"            android:gravity="center"            android:orientation="vertical" >            <TextView                android:id="@+id/tip"                android:layout_width="wrap_content"                android:layout_height="wrap_content"                android:text="@string/state" />            <TextView                android:id="@+id/lastupdate_time"                android:layout_width="wrap_content"                android:layout_height="wrap_content" />        </LinearLayout>        <ProgressBar            android:id="@+id/progress"            style="?android:attr/progressBarStyleSmall"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_toLeftOf="@id/layout"            android:layout_marginRight="20dip"            android:visibility="gone" />        <ImageView            android:id="@+id/arrow"            android:layout_width="wrap_content"            android:layout_height="wrap_content"            android:layout_alignTop="@+id/layout"            android:layout_marginRight="19dp"            android:layout_toLeftOf="@+id/layout"            android:src="@drawable/arrow_down" />    </RelativeLayout></LinearLayout>

2. Add it to the layout!
headView=layoutInflater.from(context).inflate(R.layout.header_layout, null);this.addHeaderView(headView);
3. adding to the layout directly does not meet the requirements. Therefore, you need to hide the layout in this step. Of course, you cannot use it with the previous blog (Android custom control (IV) directly hide, directly hide, cannot meet the requirements. Here we take the setting of the height of the head layout to a negative value of the actual height, in this way, the hidden function is implemented. When the drop-down is performed, It is not displayed all at once. OK can be used to meet the requirements in the figure.
headerHeight = headView.getMeasuredHeight();setHeaderViewHeight(-headerHeight);


/*** Set the height of the header layout ** @ param I */private void setHeaderViewHeight (int headerHeight) {headView. setPadding (headView. getPaddingLeft (), headerHeight, headView. getPaddingRight (), headView. getPaddingBottom (); // re-paint the headView. invalidate ();}

4. after running, I am white and blind. I didn't implement the desired function. That is to say, I didn't hide the head layout. Well, after tracking the code, I found that the height was 0. Guo Shen said that before measure, getMeasureWidth () and getMeasureHeight () are both zero. Well, let's first measure!

private void measureView(View view) {ViewGroup.LayoutParams lp = view.getLayoutParams();if (lp == null) {lp = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.WRAP_CONTENT);}int width = ViewGroup.getChildMeasureSpec(0, 0, lp.width);int height;int tempHeight=lp.height;if (tempHeight > 0) {height = MeasureSpec.makeMeasureSpec(tempHeight,MeasureSpec.EXACTLY);} else {height = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED);}view.measure(width, height);}

5. if the hiding succeeds, we need to implement the specific functions below. pull-down refresh, release refresh, and refresh the three statuses. The status is changed through gestures. So here we need to implement onTouch, and of course there is OnScrollListener.

You need to use firstVisibleItem to determine whether to slide the Listview up or down. If firstVisibleItem = 0, it indicates that it has reached the ListView header. Of course, you need a Boolean value to determine whether to press the slide.

@Overridepublic void onScroll(AbsListView view, int firstVisibleItem,int visibleItemCount, int totalItemCount) {this.firstVisibleItem=firstVisibleItem;}


Override onTouchEvent, judge the press by firstVisibleItem and Boolean value, lift, slide

@ Overridepublic boolean onTouchEvent (MotionEvent ev) {switch (ev. getAction () {case MotionEvent. ACTION_DOWN: if (firstVisibleItem = 0) {isRemark = true; startY = (int) ev. getY ();} break; case MotionEvent. ACTION_MOVE: onMove (ev); break; case MotionEvent. ACTION_UP: if (state = RELEASE) {state = REFRASH; reflashViewByState (); // update isRefreshListener. onRefresh ();} else if (state = PULL) {state = NONE; isRemark = false; refreshDrawableState ();} break;} return super. onTouchEvent (ev );}

The code is incomplete. Explain it first, and then attach all the code

If firstVisibleItem is 0 when you press it, it indicates that it reaches the top of the listview, And you can press it to assign the isRemark value to true. When you press it, the layout of the header is changed.

/*** Status change during the movement process ** @ param ev */private void onMove (MotionEvent ev) {if (! IsRemark) {return;} int tempY = (int) ev. getY (); int space = tempY-startY; int topPadding = space-headerHeight; switch (state) {case NONE: if (space> 0) {state = PULL; reflashViewByState () ;}break; case PULL: setHeaderViewHeight (topPadding); if (space> headerHeight + 30 & scrollState = SCROLL_STATE_IDLE) {state = RELEASE; reflashViewByState ();} break; case RELEASE: setHeaderViewHeight (topPadding); if (space 

The sliding status is determined based on the changes in the sliding and y values before the animation. When space is greater than zero, the current status changes to pull-down and refresh. If space is greater than a value, the current status changes to released and can be refreshed, when space is greater than zero or less than a certain value, the current status is pull-down refresh. When space is less than zero, the current status changes to normal. of course, when the status changes, the interface also needs to change
/*** Refresh the current page according to the status */private void reflashViewByState () {TextView tip = (TextView) headView. findViewById (R. id. tip); ImageView arrow = (ImageView) headView. findViewById (R. id. arrow); ProgressBar progress = (ProgressBar) headView. findViewById (R. id. progress); RotateAnimation anim = new RotateAnimation (0,180, RotateAnimation. RELATIVE_TO_SELF, 0.5f, RotateAnimation. RELATIVE_TO_SELF, 0.5f); anim. setDuration (1, 500); anim. setFillAfter (true); RotateAnimation anim1 = new RotateAnimation (180, 0, RotateAnimation. RELATIVE_TO_SELF, 0.5f, RotateAnimation. RELATIVE_TO_SELF, 0.5f); anim1.setDuration (500); anim1.setFillAfter (true); switch (state) {case NONE: setHeaderViewHeight (-headerHeight); arrow. clearAnimation (); break; case PULL: arrow. setVisibility (View. VISIBLE); progress. setVisibility (View. GONE); tip. setText ("pull-down refresh"); arrow. clearAnimation (); arrow. setAnimation (anim1); break; case RELEASE: arrow. setVisibility (View. VISIBLE); progress. setVisibility (View. GONE); tip. setText ("Release refresh"); arrow. clearAnimation (); arrow. setAnimation (anim); break; case REFRASH: setHeaderViewHeight (50); arrow. setVisibility (View. GONE); progress. setVisibility (View. VISIBLE); tip. setText ("refreshing"); arrow. clearAnimation (); break ;}}

The main changes on the interface are the prompts, arrows and progress. Normally, the interface is invisible. In the pull-down and refresh status, the arrows are visible and down. The prompt information is pull-down and refreshed, And the progress is invisible, release refresh status, arrow up, progress invisible, prompt information is pull-down refresh, loading status arrow invisible, progress visible, prompt information changed to refreshing

Of course, when it changes to the loading status, it also needs to load more data

public interface IsRefreshListener{public void onRefresh();}public void setIsRefreshListener(IsRefreshListener isRefreshListener){this.isRefreshListener=isRefreshListener;}

After loading the data, you must notify the listview to refresh.
/*** Get the data; */public void reflashComplete () {state = NONE; isRemark = false; reflashViewByState (); TextView lastupdatetime = (TextView) headView. findViewById (R. id. lastupdate_time); SimpleDateFormat format = new SimpleDateFormat ("MM dd, yyyy hh: mm: ss"); Date date = new Date (System. currentTimeMillis (); String time = format. format (date); lastupdatetime. setText (time );}

The custom pull-down refresh control is completed in this way. If you don't know how to leave a message, I will try my best to give you a solution. If you customize this item, you will know how to write it when you write more.

The following is the complete code for the custom pull-down refresh control:

Package com. sdufe. thea. guo. view; import java. text. simpleDateFormat; import java. util. date; 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. rotateAnimation; import android. widget. absListView; import android. widget. imageView; import android. Widget. progressBar; import android. widget. textView; import android. widget. absListView. onScrollListener; import android. widget. listView; import com. sdufe. thea. guo. r; public class PullToRefreshListView extends ListView implements OnScrollListener {View headView; int headerHeight; int firstVisibleItem; int scrollState; boolean isRemark; int startY; int state; final int NONE = 0; final int PULL = 1; final int RELEA SE = 2; final int REFRASH = 3; IsRefreshListener isRefreshListener; public PullToRefreshListView (Context context, AttributeSet attrs, int defStyle) {super (context, attrs, defStyle ); initView (context);} public PullToRefreshListView (Context context, AttributeSet attrs) {super (context, attrs); initView (context);} public PullToRefreshListView (Context context) {super (context); initView (context);} private void in ItView (Context context) {headView = LayoutInflater. from (context ). inflate (R. layout. header_layout, null); measureView (headView); headerHeight = headView. getMeasuredHeight (); setHeaderViewHeight (-headerHeight); addView (headView); setOnScrollListener (this );} /*** calculate the width and height ** @ param view */private void measureView (View view) {ViewGroup. layoutParams lp = view. getLayoutParams (); if (lp = null) {lp = new ViewGroup. LayoutParams (ViewGroup. layoutParams. MATCH_PARENT, ViewGroup. layoutParams. WRAP_CONTENT);} int width = ViewGroup. getChildMeasureSpec (0, 0, lp. width); int height; int tempHeight = lp. height; if (tempHeight> 0) {height = MeasureSpec. makeMeasureSpec (tempHeight, MeasureSpec. EXACTLY);} else {height = MeasureSpec. makeMeasureSpec (0, MeasureSpec. UNSPECIFIED);} view. measure (width, height);}/*** sets the height of the header layout ** @ pa Ram I */private void setHeaderViewHeight (int headerHeight) {headView. setPadding (headView. getPaddingLeft (), headerHeight, headView. getPaddingRight (), headView. getPaddingBottom (); // re-paint the headView. invalidate () ;}@ Overridepublic void onScrollStateChanged (AbsListView view, int scrollState) {this. scrollState = scrollState;} @ Overridepublic void onScroll (AbsListView view, int firstVisibleItem, int visibleItemC Ount, int totalItemCount) {this. firstVisibleItem = firstVisibleItem;} @ Overridepublic boolean onTouchEvent (MotionEvent ev) {switch (ev. getAction () {case MotionEvent. ACTION_DOWN: if (firstVisibleItem = 0) {isRemark = true; startY = (int) ev. getY ();} break; case MotionEvent. ACTION_MOVE: onMove (ev); break; case MotionEvent. ACTION_UP: if (state = RELEASE) {state = REFRASH; reflashViewByState (); // update data isRefreshLis Tener. onRefresh ();} else if (state = PULL) {state = NONE; isRemark = false; refreshDrawableState ();} break;} return super. onTouchEvent (ev);}/*** status change during the moving process ** @ param ev */private void onMove (MotionEvent ev) {if (! IsRemark) {return;} int tempY = (int) ev. getY (); int space = tempY-startY; int topPadding = space-headerHeight; switch (state) {case NONE: if (space> 0) {state = PULL; reflashViewByState () ;}break; case PULL: setHeaderViewHeight (topPadding); if (space> headerHeight + 30 & scrollState = SCROLL_STATE_IDLE) {state = RELEASE; reflashViewByState ();} break; case RELEASE: setHeaderViewHeight (topPadding); if (space Here is how to use it.
<com.sdufe.thea.guo.view.PullToRefreshListView        android:id="@+id/pull_to_refresh"        android:layout_width="match_parent"        android:layout_height="wrap_content"/>
The usage below is similar to that of listview. It prompts you to implement the IsRefreshListener interface and load more data in onRefresh ().

Package com. sdufe. thea. guo; import java. util. arrayList; import java. util. list; import com. sdufe. thea. guo. view. pullToRefreshListView; import com. sdufe. thea. guo. view. pullToRefreshListView. isRefreshListener; import android. OS. bundle; import android. app. activity; import android. view. menu; import android. widget. arrayAdapter; public class MainActivity extends Activity implements IsRefreshListener {PullToRefreshListView listView; ArrayAdapter <String> adapter; List <String> list; @ Overrideprotected void onCreate (Bundle savedInstanceState) {super. onCreate (savedInstanceState); setContentView (R. layout. activity_main); listView = (PullToRefreshListView) findViewById (R. id. pull_to_refresh); initData (); adapter = new ArrayAdapter <String> (this, android. r. layout. simple_list_item_1, list); listView. setAdapter (adapter);} private void initData () {list = new ArrayList <String> (); list. add ("123456789"); list. add ("123456789"); list. add ("123456789") ;}@ Overridepublic void onRefresh () {list. add ("dad"); list. add ("mom"); list. add ("I"); adapter. yydatasetchanged (); listView. reflashComplete ();}}

Today is the end. If you don't understand it, leave a message.




Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.