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.