Android (Android) how to achieve Drop-down refresh _android

Source: Internet
Author: User

The scenario we'll take here is to use a combination view to customize a layout to inherit from LinearLayout, and then add the Drop-down and ListView two child elements to the layout, and let the two child elements be vertically arranged. When initializing, let the drop head offset up the screen so that we can see only ListView. The ListView Touch event is then monitored, and if the current ListView has been scrolled to the top and the fingers are still pulling down, then the Drop-down head is displayed, the drop is refreshed, and the dropdown head is hidden. So let's do it now. To do this, create a new project named Pulltorefreshtest, first define a Drop-down layout file in the project Pull_to_refresh.xml, the code looks like this:

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android" xmlns:tools= "http:// Schemas.android.com/tools "android:id=" @+id/pull_to_refresh_head "android:layout_width=" Fill_parent "Android: layout_height= "Dip" > <linearlayout android:layout_width= "dip" android:layout_height= "dip" android:layout_ Centerinparent= "true" android:orientation= "horizontal" > <relativelayout android:layout_width= "Dip" Android: layout_height= "Dip" android:layout_weight= "" > <imageview android:id= "@+id/arrow" android:layout_width= "Wrap_ Content "android:layout_height=" wrap_content "android:layout_centerinparent= true" android:src= "@drawable/arrow"/ > <progressbar android:id= "@+id/progress_bar" android:layout_width= "dip" android:layout_height= "Dip" Android: Layout_centerinparent= "true" android:visibility= "Gone"/> </RelativeLayout> <linearlayout android: Layout_width= "Dip" android:layout_height= "dip" android:layout_weight= "" android:orientation= "vertical" > &LT TextView android:id= "@+id/description" android:layout_width= "fill_parent" android:layout_height= "Dip" Android: layout_weight= "" android:gravity= "Center_horizontal|bottom" android:text= "@string/pull_to_refresh"/> < TextView android:id= "@+id/updated_at" android:layout_width= "fill_parent" android:layout_height= "Dip" Android: layout_weight= "" android:gravity= "Center_horizontal|top" android:text= "@string/updated_at"/> </LinearLayout  > </LinearLayout> </RelativeLayout>

• In this layout, we include a drop-down indicator arrow, a Drop-down status text hint, and a time of last update. Of course, there is also a hidden rotation of the progress bar, only when it is refreshing we will show it. All the referenced strings in the layout are placed in Strings.xml, as follows:

<?xml version= "." Encoding= "utf-"?>
<resources>
<string name= "App_name" > pulltorefreshtest</string>
<string name= "Pull_to_refresh" > dropdown can refresh </string>
<string Name= "Release_to_refresh" > Release immediate refresh </string>
<string name= "refreshing" > Refreshing ...</string>
<string name= "Not_updated_yet" > has not been updated </string>
<string name= "Updated_at" > Last updated in% $s before < /string>
<string name= "Updated_just_now" > Just updated </string>
<string name= "Time_error" > Time is a problem </string>

• Then create a new Refreshableview inherits from LinearLayout, as shown in the following code:

public class Refreshableview extends LinearLayout implements Ontouchlistener {//dropdown state public static final int status_pull
_to_refresh =;
Release immediate refresh status public static final int status_release_to_refresh =//refreshing state public static final int status_refreshing =;
Refresh completed or not refreshed state public static final int status_refresh_finished =;
The speed of the pull head rollback is public static final int scroll_speed =-;
A minute millisecond value that is used to determine the last update time public static final long one_minute = *;
The millisecond value of an hour, used to determine the last update time public static final long one_hour = * One_minute;
The millisecond value of the day, used to determine the last update time public static final long one_day = * One_hour;
The January millisecond value used to determine the last update time public static final long one_month = * ONE_DAY;
A one-year millisecond value used to determine the last update time public static final long one_year = * ONE_MONTH;
string constant for the last update time, used as the Sharedpreferences key value private static final string updated_at = "Updated_at";
Dropdown Flush Callback Interface private Pulltorefreshlistener Mlistener;
Used to store the last update time private sharedpreferences preferences;
View private view header of the dropdown head;
Need to go down-pull refreshed ListView private ListView ListView; BrushNew show progress bar private ProgressBar ProgressBar;
Instructions for pulling down and releasing arrows private ImageView arrow;
Instructions for dropdown and release of the text description private TextView description;
The text description of the last update time private TextView updateat;
The layout parameters of the dropdown head are private marginlayoutparams headerlayoutparams;
The millisecond value of the last update time private long lastupdatetime;
To prevent drop-down refreshes of different interfaces from conflicting with each other during the last update time, use IDs to differentiate between private int mId =-;
The height of the dropdown head is private int hideheaderheight;
What state is currently being processed, optional values are status_pull_to_refresh,status_release_to_refresh,status_refreshing and status_refresh_finished
private int currentstatus = status_refresh_finished;;
Record what the last state was, avoiding repetitive operations private int laststatus = Currentstatus;
Finger press when the screen ordinate private float ydown;
The maximum value that the user's finger can move before being judged to be scrolled.
private int touchslop;
Whether the layout has been loaded once, where initialization in onlayout only needs to be loaded once private Boolean loadonce;
Whether the current can be pulled down, only ListView scroll to the end when the dropdown is allowed to pull private Boolean abletopull;
Drop-down refreshes the control's constructor and dynamically adds a Drop-down header layout at run time. Public Refreshableview (context, AttributeSet attrs) {Super (context, attrs); preferences =
Preferencemanager.getdefaultsharedpreferences (context); Header = LayoUtinflater.from (context). Inflate (R.layout.pull_to_refresh, NULL, TRUE);
ProgressBar = (ProgressBar) Header.findviewbyid (R.id.progress_bar);
Arrow = (ImageView) Header.findviewbyid (R.id.arrow);
Description = (TextView) Header.findviewbyid (r.id.description);
Updateat = (TextView) Header.findviewbyid (R.ID.UPDATED_AT);
Touchslop = Viewconfiguration.get (context). Getscaledtouchslop ();
Refreshupdatedatvalue ();
SetOrientation (VERTICAL);
AddView (header,);
//Perform some critical initialization actions, such as: Drag the drop head up to hide, and register the touch event with the ListView. protected void OnLayout (Boolean changed, int l, int t, int r, int b) {super.onlayout (changed, L, T, R, b); if (changed &A mp;&!loadonce) {hideheaderheight =-header.getheight (); headerlayoutparams = (marginlayoutparams)
Header.getlayoutparams ();
Headerlayoutparams.topmargin = Hideheaderheight;
ListView = (ListView) getchildat ();
Listview.setontouchlistener (this);
Loadonce = true;
}//When ListView is touched, it handles the specific logic of various drop-down refreshes. public boolean Ontouch (View V, motionevent event) {Setisabletopull (event); if (abletopull) {switch (event.getaction ()) {Case MotionEvent.ACTION_DOWN:yDown = Event.getrawy (); Ent.
Action_move:float ymove = Event.getrawy ();
int distance = (int) (ymove-ydown);
If the finger is slipping and the drop head is completely hidden, the screen dropdown event if (distance <= && headerlayoutparams.topmargin <= hideheaderheight) {
return false; } if (distance < Touchslop) {return false;} if (Currentstatus!= status_refreshing) {if (Headerlayoutparams.topmargi n >) {currentstatus = Status_release_to_refresh} else {currentstatus = Status_pull_to_refresh;}//By offsetting the dropdown header's Topmar
Gin value, to achieve the pull effect Headerlayoutparams.topmargin = (distance/) + hideheaderheight;
Header.setlayoutparams (Headerlayoutparams);
} break; Case MotionEvent.ACTION_UP:default:if (Currentstatus = = Status_release_to_refresh) {//When you release the immediate refresh state, call the task you are refreshing to new
Refreshingtask (). Execute ();
If else if (currentstatus = = Status_pull_to_refresh) {//If it is a drop-down state, invoke the task new Hideheadertask () that hides the Drop-down header. Execute (); }
//Always remember to update the information in the dropdown header if (currentstatus = Status_pull_to_refresh | | currentstatus = = status_release_to_refresh) {Updateheader
View ();
is currently in the Drop-down or release state, to let ListView lose focus, otherwise the clicked item will always be selected listview.setpressed (false);
Listview.setfocusable (FALSE);
Listview.setfocusableintouchmode (FALSE);
Laststatus = Currentstatus;
is currently in a drop-down or release state, masking the ListView scrolling event return True by returning true;
return false;
//To register a listener for the Drop-down refresh control.
In order to prevent the Drop-down refresh of different interfaces from conflicting with each other during the last update time, please be sure to pass in a different ID when the screen is registered to refresh the listener. public void Setonrefreshlistener (Pulltorefreshlistener listener, int id) {Mlistener = listener; mId = ID;}//When all refresh logic is complete
After the record is called, otherwise your ListView will always be in the refresh state. public void finishrefreshing () {currentstatus = status_refresh_finished; Preferences.edit (). Putlong (UPDATED_AT + mId,
System.currenttimemillis ()). commit ();
New Hideheadertask (). Execute ();
/////According to the current ListView scrolling state to set the {@link #ableToPull} value, each time you need to ontouch in the first execution, so that you can determine whether the current should be scrolling listview, or should be drop-down. private void Setisabletopull (Motionevent event) {View firstchild = Listview.getchildat (); if (FirsTchild!= null) {int firstvisiblepos = listview.getfirstvisibleposition (); if (Firstvisiblepos = = && FIRSTCHILD.G Ettop () = =) {if (!abletopull) {Ydown = Event.getrawy ();}//If the top edge of the first element is a distance from the parent layout value, the ListView is scrolled to the top, and the dropdown should be allowed to refresh at this time Abletopul
L = true; else {if (Headerlayoutparams.topmargin!= hideheaderheight) {headerlayoutparams.topmargin = Hideheaderheight; header.
Setlayoutparams (Headerlayoutparams);
} Abletopull = false;
} else {//If there are no elements in the ListView, you should also allow Drop-down refresh Abletopull = true;}
Updates the information in the Drop-down header. private void Updateheaderview () {if (laststatus!= currentstatus) {if (Currentstatus = = Status_pull_to_refresh) {DESCRI
Ption.settext (Getresources (). getString (R.string.pull_to_refresh));
Arrow.setvisibility (view.visible);
Progressbar.setvisibility (View.gone);
Rotatearrow (); else if (currentstatus = = Status_release_to_refresh) {Description.settext (Getresources (). GetString (
R.string.release_to_refresh));
Arrow.setvisibility (view.visible);
Progressbar.setvisibility (View.gone); RotateaRrow ();
else if (currentstatus = = status_refreshing) {Description.settext (Getresources (). getString (r.string.refreshing));
Progressbar.setvisibility (view.visible);
Arrow.clearanimation ();
Arrow.setvisibility (View.gone);
} refreshupdatedatvalue ();
}//Rotate the arrows according to the current state. private void Rotatearrow () {Float pivotx = arrow.getwidth ()/f; float Pivoty = Arrow.getheight ()/F; float fromdegrees
= f;
float todegrees = f; if (Currentstatus = = Status_pull_to_refresh) {fromdegrees = f; todegrees = f;} else if (Currentstatus = = Status_release_
To_refresh) {fromdegrees = f; todegrees = f;}
rotateanimation animation = new Rotateanimation (fromdegrees, Todegrees, Pivotx, Pivoty);
Animation.setduration ();
Animation.setfillafter (TRUE);
Arrow.startanimation (animation);
//Refresh the text description of the last updated time in the Drop-down header. private void Refreshupdatedatvalue () {lastupdatetime = Preferences.getlong (Updated_at + mId,-); Long currenttime = Syste
M.currenttimemillis ();
Long timepassed = Currenttime-lastupdatetime; Long Timeintoformat;
String Updateatvalue; if (LastUpdateTime = =-) {Updateatvalue = Getresources (). getString (R.string.not_updated_yet);} else if (Timepassed < {updateatvalue = Getresources (). getString (r.string.time_error);} else if (Timepassed < One_minute) {Updateatvalue
= Getresources (). getString (R.string.updated_just_now);
else if (timepassed < one_hour) {Timeintoformat = Timepassed/one_minute;
String value = Timeintoformat + "Minutes";
Updateatvalue = String.Format (Getresources (). getString (R.string.updated_at), value);
else if (timepassed < one_day) {Timeintoformat = Timepassed/one_hour;
String value = Timeintoformat + "Hour";
Updateatvalue = String.Format (Getresources (). getString (R.string.updated_at), value);
else if (timepassed < one_month) {Timeintoformat = Timepassed/one_day;
String value = Timeintoformat + "Days";
Updateatvalue = String.Format (Getresources (). getString (R.string.updated_at), value); else if (timepassed < one_year) {Timeintoformat = Timepassed/one_month;
String value = Timeintoformat + "month";
Updateatvalue = String.Format (Getresources (). getString (R.string.updated_at), value);
else {timeintoformat = timepassed/one_year;
String value = Timeintoformat + "year";
Updateatvalue = String.Format (Getresources (). getString (R.string.updated_at), value);
} updateat.settext (Updateatvalue);
}//Is refreshing the task, in this task will be callback registered in the Drop-down Refresh listener. Class Refreshingtask extends Asynctask<void, Integer, void> {protected void doinbackground (void ... params) {int to
Pmargin = Headerlayoutparams.topmargin; while (true) {TopMargin = TopMargin + scroll_speed; if (TopMargin <=) {topMargin =; break;} publishprogress (Topmar
gin);
Sleep ();
} currentstatus = status_refreshing;
Publishprogress ();
if (Mlistener!= null) {Mlistener.onrefresh ();} return null; } protected void Onprogressupdate (Integer ... topMargin) {Updateheaderview (); headerlayoutparams.topmargin = topmargin[
];
Header.setlayoutparams (Headerlayoutparams); }//Hide the task of the Drop-down header, this task will cause the dropdown to be hidden again when no drop-down or Drop-down refresh is completedHidden. 
Class Hideheadertask extends Asynctask<void, Integer, integer> {protected integer doinbackground (Void ... params) {
int topMargin = Headerlayoutparams.topmargin; 
while (true) {TopMargin = TopMargin + scroll_speed; if (TopMargin <= hideheaderheight) {topMargin = Hideheaderheight;
Break
} publishprogress (TopMargin);
Sleep ();
return topMargin;
} protected void Onprogressupdate (Integer ... topMargin) {headerlayoutparams.topmargin = topmargin[];
Header.setlayoutparams (Headerlayoutparams); } protected void OnPostExecute (Integer topMargin) {headerlayoutparams.topmargin = TopMargin; Header.setlayoutparams (
Headerlayoutparams);
Currentstatus = status_refresh_finished; The number of milliseconds specified for the current thread sleep. Specifies how long the current thread sleeps, in milliseconds, private void sleep (int time) {try {thread.sleep (time);} catch (Interruptedexception e) {E.printstack
Trace ();
}//Drop refreshed listener, use drop down refresh where this listener should be registered to get the refresh callback. Public interface Pulltorefreshlistener {///refresh will callback this method to write specific refresh logic within the method.
Note that this method is invoked in a child thread, and you may not have to work on the other threads for time-consuming operations.
void Onrefresh (); }
} 

• This class is the most important one in the entire Drop-down refresh function, and the comments have been written in more detail, let me explain briefly. The first defined Pull_to_refresh is dynamically added to the Refreshableview constructor as the Drop-down, and then the Drop-down head is offset up the screen in the OnLayout method, and the touch event is registered with ListView. The Ontouch method is then executed whenever the finger slides on the listview. The first line in the Ontouch method calls the Setisabletopull method to determine whether the ListView scroll to the top, only to scroll to the top to execute the following code, otherwise it is considered normal listview scrolling without any processing. When the ListView scroll to the top, if the finger is still dragging down, it will change the offset of the drop head, so that the dropdown head out, the pull distance set for the finger to move 1/2 of the distance, so that the feeling of tension. If the pull distance is large enough, the refresh operation will be performed when you let go, if the distance is not large enough, just to hide the dropdown head again.

• The specific refresh operation is performed in Refreshingtask, where the Onrefresh method of the Pulltorefreshlistener interface is recalled in the Doinbackground method. This is also an interface that you have to implement when using Refreshableview, because the logic of the specific refresh should be written in the Onrefresh method, followed by a demonstration of the method used.

• Each time in the Drop-down will also call the Updateheaderview method to change the data in the dropdown, such as the direction of the arrow rotation, the change in the description of the Drop-down text. For a deeper understanding, please read the code in Refreshableview carefully.

Now that we've done all the features of the Drop-down refresh, let's take a look at how to introduce a drop-down refresh in the project. Open or create a new activity_main.xml as the layout of the program's main interface, adding the following code:

<relativelayout xmlns:android= "http://schemas.android.com/apk/res/android"
xmlns:tools= "http:// Schemas.android.com/tools "
android:layout_width=" match_parent "
android:layout_height=" Match_parent "
tools:context= ". Mainactivity ">
<com.example.pulltorefreshtest.refreshableview
android:id=" @+id/refreshable_view "
android:layout_width= "fill_parent"
android:layout_height= "fill_parent" >
<listview
Android:id= "@+id/list_view"
android:layout_width= "fill_parent"
android:layout_height= "Fill_parent" >
</ListView>
</com.example.pulltorefreshtest.RefreshableView>

• We can see that we have added a ListView to the custom Refreshableview, which means that the ListView has been added to the Drop-down refresh function, it is so simple! Then we'll look at the main activity of the program, open or create a new mainactivity, and add the following code:

 public class Mainactivity extends activity {Refreshableview Refreshableview;
ListView ListView;
Arrayadapter<string> adapter;
string[] items = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"}; protected void OnCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate); Requestwindowfeature (
Window.feature_no_title);
Setcontentview (R.layout.activity_main);
Refreshableview = (Refreshableview) Findviewbyid (R.id.refreshable_view);
ListView = (ListView) Findviewbyid (R.id.list_view); adapter = new Arrayadapter<string> (this, Android.
R.layout.simple_list_item_, items);
Listview.setadapter (adapter); Refreshableview.setonrefreshlistener (New Pulltorefreshlistener () {public void Onrefresh () {try {thread.sleep ();} CATC
H (interruptedexception e) {e.printstacktrace ();} refreshableview.finishrefreshing ();
}
}, ); }
}

• As you can see, we register a listener by calling the Refreshableview Setonrefreshlistener method, and when ListView is refreshing, it recalls the Onrefresh method of the listener, and the exact logic of the refresh is handled here. And this method has automatically opened the thread, can be directly in the Onrefresh method of time-consuming operations, such as to the server request the latest data, etc., where I simply let the thread sleep for 3 seconds. Also at the end of the Onrefresh method, be sure to call the Finishrefreshing method in Refreshableview, which is used to notify the Refreshableview that the refresh is over, Otherwise our ListView will always be in the state of being refreshed.

• Do not know if you have noticed, setonrefreshlistener this method actually has two parameters, we have just passed a humble 0. So what is the second parameter used for? Because Refreshableview is more intelligent, it will automatically help us record the last time the refresh was completed, and then drop down to show how long it has been since the last refresh. This is a very useful function, so that we do not have to manually record and calculate time, but there is a problem.

• If currently we have three places in the project to use the Drop-down refresh function, now in a place to refresh, the other two time will follow the change! Because the time that the refresh was completed is recorded in the configuration file, the profile time that was read at the other two was changed because the configuration file was changed in one place.

• What's the solution? That is, each place where you use the drop-down refresh to pass a different ID to the second parameter of the Setonrefreshlistener method. In this way, the last refresh time is recorded separately, and it will not affect each other.

• Let's run it and see how it works.

• The effect looks very good. Let's conclude by summarizing the introduction of the ListView Drop-down Refresh feature in the project in just three steps:

1. Add custom Refreshableview to the activity's layout file and include ListView in it.

2. Call the Refreshableview Setonrefreshlistener method to register the callback interface in the activity.

3. At the end of the Onrefresh method, remember to call the Finishrefreshing method of the Refreshableview to notify the end of the refresh.

Related Article

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.