Android pull-down refresh ListView introduction and implementation code

Source: Internet
Author: User
Tags gety

In general, we found that the difference between the pull-down refresh list and the General List is that when the scroll bar is at the top, pulling down the whole list will be pulled down, the prompt for releasing and refreshing is displayed. From this we can see that when building this pull-down refresh component, we only need to inherit the ListView, And Then override onTouchEvent to implement it. In addition, to be referenced in the xml layout file, you also need a constructor with the Context parameter and AttributeSet.

On the surface, this is probably the case. On the other hand, the refreshing behavior does not seem to have been defined, such as what to do before refreshing, what to do during refreshing, and what to do after refreshing. These behaviors are written to an interface and then implemented by the component.

In the implementation of the entire component, the subject part is naturally the onTouchEvent part. Here we need to make some instructions. In ListView, data scrolling is different from ListView. scrollTo. Data scrolling is about the adapter. Therefore, if the entire drop-down list is not met, onTouchEvent should return super. onTouchEvent (ev) so that the original OnTouchEvent of the ListView component can be processed.

Considering that the component id and the layout of the header need to be defined in advance, and I want to apply this component to multiple projects, I will implement this component as a Library.

The following is the specific implementation code.

First, let's take a look at the layout file chenzong_push_refresh_header.xml in the header:

Copy codeThe Code is as follows: <? Xml version = "1.0" encoding = "UTF-8"?>
<RelativeLayout xmlns: android = "http://schemas.android.com/apk/res/android"
Android: layout_width = "match_parent"
Android: layout_height = "40dip"
>
<ImageView
Android: layout_width = "30dip"
Android: layout_height = "40dip"
Android: background = "@ drawable/arrow_down"
Android: layout_alignParentLeft = "true"
Android: id = "@ + id/push_refresh_header_img"
Android: layout_marginLeft = "10dip"
/>
<ProgressBar
Android: layout_width = "40dip"
Android: layout_height = "40dip"
Android: layout_alignParentLeft = "true"
Android: layout_marginLeft = "10dip"
Android: id = "@ + id/push_refresh_header_pb"
Style = "@ android: style/Widget. ProgressBar. Inverse"
Android: visibility = "gone"/>
<LinearLayout
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: layout_centerInParent = "true"
Android: orientation = "vertical"
>
<TextView
Android: layout_width = "wrap_content"
Android: layout_height = "wrap_content"
Android: text = "the last update was in :"
Android: textColor = "#000000"
/>
<TextView
Android: layout_height = "wrap_content"
Android: layout_width = "wrap_content"
Android: id = "@ + id/push_refresh_header_date"
Android: textColor = "#000000"
Android: text = "08:03:38"/>
</LinearLayout>
</RelativeLayout>

Arrows, processBar, And the last refresh time. the header file contains these three elements.

Refresh behavior interface RefreshOperation code:

Copy codeThe Code is as follows: public interface RefreshOperation {
Public void OnRefreshStart ();
Public void OnRefreshing ();
Public void OnRefreshEnd ();
}

Arrow_rotate.xml:

Copy codeThe Code is as follows: <? Xml version = "1.0" encoding = "UTF-8"?>
<Rotate
Xmlns: android = "http://schemas.android.com/apk/res/android"
Android: interpolator = "@ android: anim/linear_interpolator"
Android: fromDegrees = "0"
Android: toDegrees = "180"
Android: duration= "300"
Android: Required Tx = "50%"
Android: Ty = "50%"
Android: fillAfter = "true"
Android: repeatCount = "0">

</Rotate>

After these files and some resource files are prepared, the following figure shows the implementation of the PushRefreshList refresh list in the drop-down list:

Copy codeThe Code is as follows: package com. chenzong;

Import java. util. Calendar;

Import com. doall. pushrefreshlist. R;

Import android. content. Context;
Import android. OS. Handler;
Import android. OS. Message;
Import android. util. AttributeSet;
Import android. view. LayoutInflater;
Import android. view. MotionEvent;
Import android. view. View;
Import android. view. animation. Animation;
Import android. view. animation. AnimationUtils;
Import android. widget. ListView;
Import android. widget. TextView;

Public class PushRefreshList extends ListView implements RefreshOperation {

Private int header_layout = R. layout. chenzong_push_refresh_header;
// Header file
Private int arrow_down = R. drawable. arrow_down;
// Resource down by Arrow
Private int arrow_up = R. drawable. arrow_up;
// Resources on the top of the arrow
Private int img = R. id. push_refresh_header_img;
// Display the Control id of the arrow
Private int pb = R. id. push_refresh_header_pb;
// Progress bar during refresh
Private int startPoint = 0;
// Start point of the touch
Private RefreshOperation refresh;
// Refresh the object of the action
Private Animation animation = null;
Private Context context;
Private View headerView;
Private int minPushHeight;

Private final String TAG = "pushRefresh ";

Public PushRefreshList (Context cotext, AttributeSet attrs ){
Super (context, attrs );
View empty = new View (context );
// Determine whether it is at the top of the list. this. getFirstVisiblePosition () is usually used. Here, a zero View with a height is created and added between headerView and data.
This. addHeaderView (empty );
LayoutInflater inflater = LayoutInflater. from (context );
HeaderView = inflater. inflate (header_layout, null );
This. addHeaderView (headerView );
This. setRefreshOperation (this );
This. context = context;

}

@ Override
Protected void onLayout (boolean changed, int l, int t, int r, int B ){
This. minPushHeight = headerView. getMeasuredHeight ();
// Obtain the trigger height of the pull-down refresh
Super. onLayout (changed, l, t, r, B );
}

Private boolean canHandleEvent (int dy)
{
Return (dy <0 & this. getFirstVisiblePosition () = 0 &&! IsPbVisible ());
}

@ Override
Public boolean onTouchEvent (MotionEvent ev ){

Int action = ev. getAction ();
Switch (action)
{
Case MotionEvent. ACTION_DOWN:
StartPoint = (int) ev. getY ();
Break;
Case MotionEvent. ACTION_MOVE:
Int dy = startPoint-(int) ev. getY ();
If (canHandleEvent (dy ))
{
If (animation = null)
{
If (Math. abs (this. getScrollY ()> = this. minPushHeight)
{
Animation = AnimationUtils. loadAnimation (context, R. anim. arrow_rotate );
View mView = headerView. findViewById (img );
MView. startAnimation (animation );
This. setScrollbarFadingEnabled (true );
}
}
This. scrollTo (0, dy/2 );
Return true;
}
Break;
Case MotionEvent. ACTION_UP:

This. setScrollbarFadingEnabled (false );
If (animation! = Null)
{
SetImgBackgroundUp ();
SwitchCompent (View. INVISIBLE, View. VISIBLE );
This. scrollTo (0,-minPushHeight );
PushRefreshList. this. refresh. OnRefreshStart ();
New Thread (mRunnable). start ();
Animation = null;
}
Else
This. scrollTo (0, 0 );
Break;
}
Return super. onTouchEvent (ev );
}

Private Runnable mRunnable = new Runnable ()
{

@ Override
Public void run (){
PushRefreshList. this. refresh. OnRefreshing ();
MHandler. obtainMessage (). sendToTarget ();
}
};

Private Handler mHandler = new Handler ()
{
@ Override
Public void handleMessage (Message msg ){
PushRefreshList. this. refresh. OnRefreshEnd ();
PushRefreshList. this. scrollTo (0, 0 );
PushRefreshList. this. setImgBackgroundDown ();
PushRefreshList. this. switchCompent (View. VISIBLE, View. GONE );
TextView TV = (TextView) headerView. findViewById (R. id. push_refresh_header_date );
TV. setText (this. getDateStr ());
}

Private String getDateStr ()
{
Calendar ca = Calendar. getInstance ();
Int year = ca. get (Calendar. YEAR );
Int month = ca. get (Calendar. MONTH );
Int date = ca. get (Calendar. DATE );
Int hour = ca. get (Calendar. HOUR );
Int mintes = ca. get (Calendar. MINUTE );
Int second = ca. get (Calendar. SECOND );
Return year + "-" + (month + 1) + "-" + date + "" + hour + ":" + mintes + ":" + second;
}
};

Private void switchCompent (int imgStatus, int pbStatus)
{
View img = headerView. findViewById (R. id. push_refresh_header_img );
Img. clearAnimation ();
// If clearAnimation is not called, setVisibility (View. GONE) becomes invalid.
Img. setVisibility (imgStatus );
HeaderView. findViewById (R. id. push_refresh_header_pb). setVisibility (pbStatus );
}

Private boolean isPbVisible ()
{
Return View. VISIBLE = headerView. findViewById (R. id. push_refresh_header_pb). getVisibility ();
}

Private void setImgBackgroundUp ()
{
View mView = headerView. findViewById (this. img );
MView. setBackgroundResource (arrow_up );
}

Private void setImgBackgroundDown ()
{
View mView = headerView. findViewById (this. img );
MView. setBackgroundResource (arrow_down );
}

Public void setRefreshOperation (RefreshOperation refresh)
{
This. refresh = refresh;
}

@ Override
Public void OnRefreshStart (){

}

@ Override
Public void OnRefreshing (){

}

@ Override
Public void OnRefreshEnd (){
}

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.