Android Custom ListView Implementation Dropdown Refresh _android

Source: Internet
Author: User
Tags gety

Present the effect chart first


Today's app, which does not have the point of sliding refresh function, is simply too outdated. Because of the need for more, so naturally open source is also more. But if you want to quote open Source Library, it is very troublesome, such as Pulltorefreshview this library, if the open source code are transplanted to the project, this is a very cumbersome thing, if the use of dependent functions, for obsessive-compulsive disorder I, and very uncomfortable. Now there are a variety of custom ListView implementation Pulltorefreshlistview control, nothing more than adding a control in the header, through the setpadding way to change the display effect. The effect has been too out, the Ruyi found that Google's swiperefreshlayout implementation is very good, but I found that this control on the part of the mobile phone effect is not the same, estimated and V7 packet related. So there is this article to customize this favorite effect.
First, a general description of the implementation principle:
1, rewrite the ListView ontouchevent, in the method according to the finger sliding distance and the critical value judgment, determines the current state, divides into four states: Release_to_refresh, Pull_to_refresh, refreshing, Done four states, respectively, for release refresh, pull refresh, refreshing, default state.
2, rewrite the ListView OnDraw method, according to the different state values, display different graphical representations.
3, according to the different sliding distance, display different transparency, arc angle value, the overall graphics coordinates and so on.
4, the change of the graph divides into two kinds: 1, manual trigger, slide a little distance to update a little coordinates. such as Pull_to_refresh state, suitable for ontouchevent in the action_move in the trigger. 2, animation automatic trigger, such as refreshing state and done state, suitable in the ontouchevent in the Action_up method trigger, the finger a release automatically triggered animation effect.
5, must be set in the refresh listener can slide, otherwise it is a common listview.

The code is simple, there are only two files, and there are very detailed comments:
Pulltorefreshlistview class:

 Package cc.wxf.view.pull;
Import Android.content.Context;
Import Android.graphics.Canvas;
Import Android.util.AttributeSet;
Import android.view.MotionEvent;
Import Android.view.View;
Import Android.widget.AbsListView;
 
Import Android.widget.ListView;
 /** * Created by CCWXF on 2016/3/30. * * public class Pulltorefreshlistview extends ListView implements Abslistview.onscrolllistener {public final static I
  NT Release_to_refresh = 0;
  Public final static int pull_to_refresh = 1;
  Public final static int refreshing = 2;
 
  Public final static int done = 3;
  The sliding distance to the refresh condition is public final static int touch_slop = 160;
  Determines whether the y-coordinate of the first press is recorded as private Boolean isrecored;
  The y-coordinate is private int starty when the record is first pressed;
  ListView first item private int firstitemindex;
  Current status private int state;
  Whether can refresh, only set the listener to refresh private Boolean isrefreshable;
 
  Refresh Mark private Pullmark mark;
  Private Onrefreshlistener Refreshlistener;
Private Onscrollbuttomlistener Scrollbuttomlistener; 
  Public Pulltorefreshlistview {Super (context);
  Init (context);
    Public Pulltorefreshlistview (context, AttributeSet attrs) {Super (context, attrs);
  Init (context); } private void Init (context context) {//Turn off hardware acceleration, otherwise pullmark shadow will not appear setlayertype (view.layer_type_software, NULL)
    ;
    Setonscrolllistener (this);
    Mark = new Pullmark (this);
    state = done;
  Isrefreshable = false; @Override public void onscrollstatechanged (Abslistview view, int scrollstate) {if (Scrollbuttomlistener!= nu LL) {if (scrollstate = = Onscrolllistener.scroll_state_idle) {if (view.getlastvisibleposition () = = View.get
        Adapter (). GetCount ()-1) {scrollbuttomlistener.onscrolltobuttom ();  @Override public void Onscroll (Abslistview view, int firstvisibleitem, int visibleitemcount, int
  Totalitemcount) {firstitemindex = Firstvisibleitem; } @Override protected void OnDraw(Canvas Canvas)
    {Super.ondraw (canvas);
  Mark.ondraw (canvas); @Override protected void onmeasure (int widthmeasurespec, int heightmeasurespec) {int width = Measurespec.gets
    Ize (WIDTHMEASURESPEC);
    Mark.setcenterx (WIDTH/2);
  Super.onmeasure (Widthmeasurespec, Heightmeasurespec); @Override public boolean ontouchevent (Motionevent event) {if (!isrefreshable) {return super.ontoucheve
    NT (event);
        Switch (event.getaction ()) {Case MotionEvent.ACTION_DOWN:handleActionDown (event);
 
      Break
        Case MotionEvent.ACTION_UP:handleActionUp ();
 
      Break
        Case MotionEvent.ACTION_MOVE:handleActionMove (event);
      Break
    Default:break;
  Return Super.ontouchevent (event);
 
    } private void Handleactionmove (Motionevent event) {int tempy = (int) event.gety ();
      if (!isrecored && firstitemindex = = 0) {isrecored = true;
   Starty = Tempy; } if (state!= refreshing && isrecored) {if (state = = Release_to_refresh) {setselection (0);
        if ((Tempy-starty < Touch_slop) && (Tempy-starty) > 0) {state = Pull_to_refresh;
        } if (state = = Pull_to_refresh) {setselection (0);
        if (Tempy-starty >= touch_slop) {state = Release_to_refresh;
        else if (tempy-starty <= 0) {state = done;
        } if (state = = done) {if (Tempy-starty > 0) {state = Pull_to_refresh;
    } mark.change (state, Tempy-starty);
      The private void Handleactionup () {if (state = = Pull_to_refresh) {state = done;
    Mark.changebyanimation (state);
      else if (state = = Release_to_refresh) {state = refreshing;
      Mark.changebyanimation (state);
    Onrefresh ();
  } isrecored = false; } private void Handleactiondown (motionevent Event) {if (Firstitemindex = = 0 &&!isrecored) {isrecored = true;
    Starty = (int) event.gety ();
    } private void Onrefresh () {if (Refreshlistener!= null) {Refreshlistener.onrefresh ();
    } public void Startrefresh () {state = refreshing;
    Mark.changebyanimation (state);
  Onrefresh ();
    public void Stoprefresh () {state = done;
  Mark.changebyanimation (state);
    public void Setonrefreshlistener (Onrefreshlistener refreshlistener) {this.refreshlistener = Refreshlistener;
  Isrefreshable = true;
  /** * Refresh listener/public interface Onrefreshlistener {public void Onrefresh ();  } public void Setonscrollbuttomlistener (Onscrollbuttomlistener scrollbuttomlistener) {This.scrollbuttomlistener =
  Scrollbuttomlistener;
  /** * slide to the lowest end trigger listener/public interface Onscrollbuttomlistener {public void Onscrolltobuttom ();
 }
 
}

Refresh Flag class:

 Package cc.wxf.view.pull;
Import Android.graphics.Canvas;
Import Android.graphics.Color;
Import Android.graphics.Paint;
Import Android.graphics.RectF;
 
Import Android.os.Handler;
 /** * Created by CCWXF on 2016/3/30.
  * * public class Pullmark {//Background panel radius, color private static final int radius_pan = 40;
  private static final int color_pan = Color.parsecolor ("#fafafa");
  The radius of the panel shadow, the color private static final int radius_shadow = 5;
  private static final int color_shadow = Color.parsecolor ("#d9d9d9");
  The radius of the arc in the middle of the panel, the color, the coarseness, the starting angle of the drawing is private static final int radius_arrows = 20;
  private static final int color_arrows = Color.green;
  private static final int bound_arrows = 6;
  private static final int start_angle = 0;
  Change rate of starting angle, overall drawing angle, overall drawing transparency private static final int ratio_satrt_angle = 3;
  private static final int all_angle = 270;
  private static final int all_alpha = 255;
  Animation height gradient ratio, time refresh interval private static final float ratio_touch_slop = 7f; Private static final long RAtio_animation_duration = 10;
  Private Pulltorefreshlistview ListView;
  The x, y coordinates of the midpoint, the y-coordinate at the time of the initial concealment, private float donecentery =-(Radius_pan + Radius_shadow)/2;
  private float CenterX;
  private float centery = donecentery;
  The angle to start drawing, the angle to draw, transparency private int startangle = Start_angle;
  private int sweepangle = StartAngle;
  private int alpha;
  The Radian variation ratio, according to the overall height and the overall radian angle ratio decides the private float Radioangle = All_angle * 1.0F/PULLTOREFRESHLISTVIEW.TOUCH_SLOP;
  Transparency change ratio, according to the overall height and overall transparency of the ratio decided to private float Radioalpha = All_alpha * 1.0F/PULLTOREFRESHLISTVIEW.TOUCH_SLOP;
  Pulltorefreshlistview states private int state;
  The current finger sliding distance private float mtouchlength;
  Whether to start the rotation animation private Boolean isrotateanimation = false;
  Brush private Paint Mpaint = new Paint (Paint.anti_alias_flag);
 
  Private Handler Handler = new Handler ();
  Public Pullmark (Pulltorefreshlistview listView) {this.listview = ListView; /** * Sets the midpoint x-coordinate of the drawing, implemented in Pulltorefreshlistview Onmeasure * @parAM CenterX */public void Setcenterx (int centerx) {This.centerx = CenterX; /** * Represents a normal data change that triggers * @param state * @param mtouchlength/public void ch in ontouchevent action_move
    Ange (int state, float mtouchlength) {this.state = state;
    This.mtouchlength = Mtouchlength;
    Change the plotted y-coordinate centery = donecentery + mtouchlength;
    Changes the transparency alpha = (int) (MTOUCHLENGTH * radioalpha) of the drawing;
    if (Alpha > All_alpha) {alpha = All_alpha;
    }else if (Alpha < 0) {alpha = 0;
    //Change the starting angle of the drawing startangle = StartAngle + ratio_satrt_angle;
    if (startangle >= 360) {startangle = 0;
    //Change the curvature angle of the drawing sweepangle = (int) (MTOUCHLENGTH * radioangle);
    if (Sweepangle > All_angle) {sweepangle = All_angle;
    }else if (Sweepangle < 0) {sweepangle = 0;
  } listview.invalidate (); /** * Represents a change in the animation, triggering * @param state/Public Stoprefresh in ontouchevent action_up or manual Startrefresh and manual VoiD changebyanimation (final int state) {this.state = state;
    if (state = = Pulltorefreshlistview.done) {//End rotation animation (turn off the effect of refreshing) Isrotateanimation = false;
  ///Slowly change to the starting position handler.postdelayed (new Runnablemove (state), ratio_animation_duration);
    /** * Initiate mobile processing/public class Runnablemove implements runnable{private int state;
    private int destination;
 
    private float slop;
      Public runnablemove (int state) {this.state = state;
        if (state = = pulltorefreshlistview.done) {destination = 0;
      Slop = Ratio_touch_slop;
        }else if (state = = pulltorefreshlistview.refreshing) {destination = Pulltorefreshlistview.touch_slop;
      Slop = Ratio_touch_slop * 5;
        @Override public void Run () {if (Mtouchlength > Destination) {mtouchlength-= slop;
        Change (state, mtouchlength);
      Handler.postdelayed (this, ratio_animation_duration); }else{if (state = =Pulltorefreshlistview.done) {//Direct coordinate initialization, otherwise there will be a little bit of error centery = Donecentery;
        Listview.invalidate ();
          }else if (state = = pulltorefreshlistview.refreshing) {//Start rotation animation effect isrotateanimation = true;
        Handler.postdelayed (New Runnablerotate (), ratio_animation_duration); /** * Rotation Animation processing * * Public class Runnablerotate implements runnable{@Override Publ
        IC void Run () {if (isrotateanimation) {//Starts animation rotation effect StartAngle = startangle + ratio_satrt_angle;
        if (startangle >= 360) {startangle = 0;
        } listview.invalidate ();
      Handler.postdelayed (this, ratio_animation_duration);
      }else{//back to initial position handler.postdelayed (new Runnablemove (state), ratio_animation_duration); */** * Draw Refresh Icon logo * @param mcanvas/public void OnDraw (Canvas mcanvas) {//Draw background disc and Shadow MPa Int.setstyle (Paint.Style.FILL);
    Mpaint.setcolor (Color_pan);
    Mpaint.setshadowlayer (Radius_shadow, 0, 0, Color_shadow);
    Mcanvas.drawcircle (CenterX, CenterY, Radius_pan, Mpaint);
    Draw Arc Mpaint.setstyle (Paint.Style.STROKE);
    Mpaint.setcolor (color_arrows);
    Mpaint.setstrokewidth (bound_arrows);
    Mpaint.setalpha (Alpha); Mcanvas.drawarc (New RECTF (Centerx-radius_arrows, centery-radius_arrows, CenterX + radius_arrows, CenterY + RADIUS_ARRO
  WS), StartAngle, Sweepangle, False, Mpaint);
 }
}

When used, you must set up the listener in order to effectively slide:

Final Pulltorefreshlistview ListView = (pulltorefreshlistview) Findviewbyid (R.id.listview);
    arrayadapter<string> adapter = new Arrayadapter<string> (this, Android. R.layout.simple_list_item_1, new string[]{
      "Test 1", "Test 2", "Test 3", "Test 4", "Test 5", "Test 6",
    });
    Listview.setadapter (adapter);
    Listview.setonrefreshlistener (New Pulltorefreshlistview.onrefreshlistener () {
      @Override public
      Void Onrefresh () {
        new Handler (). postdelayed (New Runnable () {
          @Override public
          void Run () {
            Listview.stoprefresh ();}}
        ,%);
      }
    );

Two source code files are done, the demo project will not provide, very simple.

The above is the entire content of this article, I hope to help you learn, but also hope that we support the cloud habitat community.

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.