Android Custom Drop-down Refresh control refreshableview_android

Source: Internet
Author: User
Tags abs touch

This is in the understanding of the lower-pull refresh function under the principle of the product, Drop-down refresh can be said to be a domestic app in the necessary functions, even Google for this out of the Swiperefreshlayout, a MD-style drop-down refresh.
However, the MD style seems very difficult at home, not only is the mainstream of the domestic system is still 4.4 reasons, there are user habits, a little bit more, after reading a lot of blogs, I suddenly want to write a swiperefreshlayout compatible with all the control of the Drop-down refresh, not just ListView, hope it can also accommodate ordinary view and ScrollView, after two days of struggle, finally done, because my purpose is just want to pull the refresh, so the function is very few, however, if you can pull down the refresh is done, other functions, you can slowly pile up.

The reason for the new system, can not give the appropriate GIF, only screenshot:

The first photo shows TextView:

The second chapter of the picture shows the ListView:

The third chapter of the picture shows the ScrollView:

Basically this is the successful control I tested, compatible with the common view is the simplest, more complex is ListView and ScrollView.

train of thought: my idea and most blogs are the same, custom a viewgroup, and then will contain the control to drag the touch event to Refreshableview processing, dynamic change Headview margintop value, above. Of course, there are some details to note, such as the processing of the return value of the Ontouch method, and the processing of the margintop value of the child View.

Source

First the Headview layout file:

<?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"
 android:orientation= "Horizontal" >


 <imageview
 android:id= "@+id/imageview_" Down "
 android:layout_width=" 14DP "
 android:layout_height=" 24DP "
 android:padding=" 2DP "
 Android : src= "@drawable/svg_down" "/>

 <progressbar
 android:visibility="
 Gone "android:id=" @+id/ ProgressBar "
 style=" "Android:attr/progressbarstyle"
 android:layout_width= "20DP"
 android:layout_ height= "20DP"
 android:progressdrawable= "@drawable/progressbar"/>

 <textview
 android: padding= "15DP"
 android:id= "@+id/textview"
 android:layout_width= "wrap_content"
 android:layout_ height= "Wrap_content"
 android:text= "@string/pull_to_refresh"
 android:textsize= "16sp"/>

</ Linearlayout>

The next step is the all-important class Refreshableview:

Package Com.pull2refresh;
Import Android.animation.ObjectAnimator;
Import Android.animation.ValueAnimator;
Import Android.annotation.TargetApi;
Import Android.content.Context;
Import Android.os.Build;
Import Android.util.AttributeSet;
Import Android.util.Log;
Import Android.view.LayoutInflater;
Import android.view.MotionEvent;
Import Android.view.View;
Import android.view.ViewConfiguration;
Import Android.view.ViewGroup;
Import android.view.animation.RotateAnimation;
Import Android.widget.ImageView;
Import Android.widget.LinearLayout;
Import Android.widget.ProgressBar;

Import Android.widget.TextView;

Import SHIKE.XIANROU.COM.PULL2REFRESH.R;
 /** * Created by cjh on 16-9-6.  * * public class Refreshableview extends LinearLayout implements View.ontouchlistener {private static final String TAG =

 "Refreshableview"; private static final int refreshing = 0;//refreshing private static final int ORIGINAL = refreshing + 1;//initial state private static Final int release_to_refreshing = ORIGINAL + 1;Release the state that is about to be refreshed private int current_status = original;//Current latest status private LinearLayout headview;//refresh layout Private TextView

 textview;//Refresh layout text hint private ImageView imageview;//refresh layout arrows private ProgressBar progressbar;//Refresh the progress bar in the layout Private view view;//finger-controlled drop-down View private int hideheight;//Refresh layout to hide the height of the private Boolean isablepull;//can be pulled down, for example when Curre Nt_status = Refreshiing is not the following pull-dragged private float ydown;//finger-pressed coordinates private int touchslop = Viewconfiguration.get (getcont Ext ()). Getscaledtouchslop ()//limit value to prevent finger from touching, too sensitive private Boolean firstlayout = true;//The first time to call onlayout false private in

 T maxmargintop;//refresh layout can pull down the maximum distance private marginlayoutparams marginlayoutparams;//Refresh layout marginlayoutparams

 Private String Pull_to_refresh = "Dropdown can be refreshed";

 Private String Release_to_refresh = "Release immediate refresh";


 Private String refreshing = "refreshing ..."; private int original_margin = 0;//for Drop-down view presence margintop The processing of this special value is public interface Pulltorefreshlistener {void Onrefresh
 (); Private PulltoRefreshlistener Pulltorefreshlistener; public void Addpulltorefreshlistener (Pulltorefreshlistener pulltorefreshlistener) {This.pulltorefreshlistener =
 Pulltorefreshlistener;
 Public Refreshableview {Super (context);
 Init ();
 Public Refreshableview (context, AttributeSet attrs) {Super (context, attrs);
 Init ();
 Public Refreshableview (context, AttributeSet attrs, int defstyleattr) {Super (context, attrs, defstyleattr);
 Init (); } @TargetApi (Build.version_codes. Lollipop) public Refreshableview (context, AttributeSet attrs, int defstyleattr, int defstyleres) {Super (context
 , Attrs, defstyleattr, defstyleres);
 Init (); private void Init () {Headview = (linearlayout) layoutinflater.from (GetContext ()). Inflate (R.layout.refresh_layout, Nu
 ll, true);
 ImageView = (ImageView) Headview.findviewbyid (R.id.imageview_down);
 ProgressBar = (ProgressBar) Headview.findviewbyid (R.id.progressbar); TextView = (TextView) headview.findviewByid (R.id.textview);
 Progressbar.setvisibility (View.gone);
 SetOrientation (VERTICAL);
 AddView (Headview, 0); @Override protected void OnLayout (Boolean changed, int l, int t, int r, int b) {super.onlayout (changed, L, T, R, B)
 ;
 LOG.D (TAG, "onlayout");
  if (changed && firstlayout) {//Handle the view's touch time to Refreshableview to deal with view = Getchildat (1);

  View.setontouchlistener (this);

  The maximum value of the refresh layout margintop is set to the height of the refresh head maxmargintop = Headview.getheight ();
  To completely hide the control, the hidden height is set to the height of the control Hideheight =-headview.getheight ();
  Marginlayoutparams = (marginlayoutparams) headview.getlayoutparams ();
  Marginlayoutparams.topmargin = Hideheight;

  Headview.setlayoutparams (Marginlayoutparams);

  The firstlayout must be set to false, otherwise the Headview will be placed as the initial hidden state firstlayout = False in how the touch is handled, when the setlayoutparams is invoked. If the child view is a viewgroup then you need to compute the margintop value of the child view, because if MarginTop is not 0, then the y-coordinate of the child view is different from the coordinates of the parent view if (view instanceof
  ViewGroup) {int[] childlocations = new int[2]; Int[] Viewlocations = new Int[2];
  View.getlocationonscreen (viewlocations);
  ((viewgroup) view). Getchildat (0). Getlocationonscreen (childlocations);
  Original_margin = childlocations[1]-viewlocations[1];
  LOG.D (TAG, "OnLayout viewlocations[1]" + viewlocations[1]);
  LOG.D (TAG, "OnLayout locations[1]" + childlocations[1]);
  LOG.D (TAG, "onlayout original_margin" + original_margin);
  @Override public boolean Ontouch (view view, Motionevent motionevent) {if (Pulltorefreshlistener!= null) {
  Isablepull ();
   if (isablepull) {switch (motionevent.getaction ()) {Case MotionEvent.ACTION_DOWN:yDown = Motionevent.getrawy ();

   Break
   Case MotionEvent.ACTION_MOVE:float Ymove = Motionevent.getrawy ();

   float distance = Ymove-ydown; If the gesture is up and the movement of the gesture on the y-axis is less than the boundary value, then the if (Distance < 0 | |) is not processed.

   Math.Abs (distance) < Touchslop) return false;
   The distance of the margintop is 1/2 of the gesture distance, which forms the effect of laborious delay marginlayoutparams.topmargin = (int) (DISTANCE/2 + hideheight); LOG.D (TAG, "TopMargin" + marginlayoutparams.topmargin); If it is greater than the maximum margintop value, the value is placed to Maxmargintop if (marginlayoutparams.topmargin >= maxmargintop) marginlayoutparams.


   TopMargin = Maxmargintop; if (marginlayoutparams.topmargin >= 0) {//When the refresh header is fully displayed, change the state to release the refreshed state if (Current_status!= Release_to_refresh
    ING) {rotate (0, 180);
    Textview.settext (Release_to_refresh);
   } current_status = release_to_refreshing;
    else {//otherwise set to the initial state if (Current_status!= ORIGINAL) {rotate (180, 360);
    Textview.settext (Pull_to_refresh);

   } current_status = ORIGINAL;
   } headview.setlayoutparams (Marginlayoutparams);

   Break
   Case MotionEvent.ACTION_CANCEL:case MotionEvent.ACTION_UP:float yUp = Motionevent.getrawy ();
   float dis = yup-ydown; if (Dis > 0 && math.abs (dis) > Touchslop) switch (current_status) {//release refresh case Release_to_refre
    Shing:animatemargintop (marginlayoutparams.topmargin, 0); Imageview.clearanimation ();
     Imageview.setvisibility (View.gone);
     Progressbar.setvisibility (view.visible);
     Textview.settext (refreshing);
     Pulltorefreshlistener.onrefresh ();

    Break
     Initialize case Original:reset ();
     From the current value of the margintop to the hidden need of the margintop animatemargintop (Marginlayoutparams.topmargin, hideheight);
    Break

   else return false;
  Break
  return true;
 return false; /** * To determine if you can drop the * * @return/public boolean isablepull () {//Unified judgment, in fact, is mainly for view is a general view of the judgment if (Current_status!=
 refreshing) Isablepull = true;

 else Isablepull = false;
  if (view instanceof viewgroup) {isablepull = false;
  View Childview = ((viewgroup) view). Getchildat (0);
  int[] viewlocations = new int[2];
  int[] childviewlocations = new int[2];
  View.getlocationonscreen (viewlocations);

  Childview.getlocationonscreen (childviewlocations); The original_margin in this step is critical in that it is used to compatible the values of the MarginTop property of the child view, when the Y coordinate of the childview and the calculated When the parent view coordinates of the Margin value are equal, the state if (viewlocations[1] + Original_margin = = Childviewlocations[1]) Isablepull = true;
 else Isablepull = false;
 return isablepull; } private void rotate (int from, int to) {rotateanimation rotateanimation = new Rotateanimation (from, to, Imageview.get
 Width ()/2, Imageview.getheight ()/2);
 Rotateanimation.setduration (100);
 Rotateanimation.setfillafter (TRUE);
 Imageview.startanimation (rotateanimation); } private void Animatemargintop (int from, int to) {Objectanimator Objectanimator = Objectanimator.ofint (Headview, "cjh
 ", from, to);
 Objectanimator.setduration (300); Objectanimator.addupdatelistener (New Valueanimator.animatorupdatelistener () {@Override public void
  Onanimationupdate (Valueanimator valueanimator) {int margin = (int) valueanimator.getanimatedvalue ();
  Marginlayoutparams.topmargin = margin;
  Headview.setlayoutparams (Marginlayoutparams);
 }
 });
 Objectanimator.start (); public void Complete () {AnimatemarGintop (0, hideheight);
 Reset ();
 private void Reset () {rotate (180, 360);
 Textview.settext (Pull_to_refresh);
 Imageview.setvisibility (view.visible);
 Progressbar.setvisibility (View.gone);

 }

}

Use:

 <com.pull2refresh.refreshableview
 android:id= "@+id/refreshableview"
 android:layout_width= "Match_ Parent "
 android:layout_height=" wrap_content "
 android:gravity=" center ">

 < Com.pull2refresh.MTextView
  android:id= "@+id/mtextview"
  android:layout_width= "Match_parent"
  Android : layout_height= "100DP"
  android:background= "@color/colorprimary"
  android:gravity= "center"
  Android : text= "Hello world!"
  Android:textsize= "22SP"/>

 </com.pull2refresh.RefreshableView>

 Refreshableview.addpulltorefreshlistener (new
  Refreshableview.pulltorefreshlistener () {@Override public void Onrefresh () {setData ();
}
 });
 ... private void SetData () {Objectanimator objectanimator = objectanimator.offloat (TextView, "text", 1f, 100f);
 Objectanimator.setduration (3000); Objectanimator.addupdatelistener (New Valueanimator.animatorupdatelistener () {@Override public void
  Onanimationupdate (Valueanimator valueanimator) {Textview.settext ((Float) valueanimator.getanimatedvalue ());
 }
 }); Objectanimator.addlistener (New Animator.animatorlistener () {@Override public void Onanimationstart (animator Animator
  {} @Override public void Onanimationend (animator animator) {refreshableview.complete (); @Override public void Onanimationcancel (animator animator) {} @Override public void Onanimationrepeat (Anim
 Ator animator) {}});
 Objectanimator.start (); }

In my custom Refreshableview, if you do not set down the monitor, there is no pull effect, that is, does not support the dropdown

SOURCE Download: Android dropdown Refresh Control

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.

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.