ScrollView of Rebound
What you see on the Web is usually ElasticScrollView ,
There is a bug: When you click on a child control to slide, the swipe is not valid,
So I ElasticScrollView made an improvement on this issue.
Schematic diagram
Code
I did a detailed explanation in the comments.
ImportAndroid.content.Context;ImportAndroid.graphics.Rect;ImportAndroid.util.AttributeSet;ImportAndroid.view.MotionEvent;ImportAndroid.view.View;ImportAndroid.view.animation.Animation;ImportAndroid.view.animation.DecelerateInterpolator;ImportAndroid.view.animation.TranslateAnimation;ImportAndroid.widget.ScrollView;/** * Created by Tindle Wei. * * Public class elasticscrollview extends ScrollView { /** * Finger jitter Error * / Private Static Final intShake_move_value =8;/** * ScrollView interior View */ PrivateView Innerview;/** * Record the initial y position of the Innerview * / Private floatStarty;/** * Record the size position of the original Innerview * / PrivateRect Outrect =NewRect ();Private BooleanAnimationfinish =true; Public Elasticscrollview(Context context) {Super(context); } Public Elasticscrollview(context context, AttributeSet attrs) {Super(context, attrs); }/** * Inherits from View * Executes after all layout of XML is loaded */ @Override protected void onfinishinflate() {if(Getchildcount () >0) {Innerview = Getchildat (0); } }/** * Inherits from ViewGroup * Returns true, intercepts touch events * returns false, passes events to Ontouchevent () and child controls Dispatchtouchevent () */ @Override Public Boolean onintercepttouchevent(Motionevent ev) {//Judging click Child controls or press and hold child controls to slide //If the child control is clicked, returns false, the child control responds to the Click event //If you press and hold the child controls to slide, returns true, sliding the layout Switch(Ev.getaction ()) { CaseMotionevent.action_down: {starty = Ev.gety (); Break; } CaseMotionevent.action_move: {floatCurrentY = Ev.gety ();floatscrolly = Currenty-starty;//Whether to return True returnMath.Abs (scrolly) > Shake_move_value; } }//return false by default return Super. onintercepttouchevent (EV); }@Override Public Boolean ontouchevent(Motionevent ev) {if(Innerview = =NULL) {return Super. ontouchevent (EV); }Else{mytouchevent (EV); }return Super. ontouchevent (EV); } Public void mytouchevent(Motionevent ev) {if(Animationfinish) {Switch(Ev.getaction ()) { CaseMotionEvent.ACTION_DOWN:startY = Ev.gety ();Super. ontouchevent (EV); Break; CaseMotionEvent.ACTION_UP:startY =0;if(Isneedanimation ()) {animation (); }Super. ontouchevent (EV); Break; CaseMotionevent.action_move:Final floatPreY = Starty = =0? Ev.gety (): Starty;floatNowy = Ev.gety ();intDeltaY = (int) (Prey-nowy); Starty = Nowy;//When scrolling to the top or bottom no longer scrolls, move layout if(Isneedmove ()) {if(Outrect.isempty ()) {//Save the normal layout positionOutrect.set (Innerview. GetLeft (), Innerview.gettop (), innerview.ge Tright (), Innerview.getbottom ()); }//Mobile layout //Here DELTAY/2 for better Operation ExperienceInnerview.layout (Innerview.getleft (), Innerview.gettop ()-DeltaY/2, Innerview.getright (), Innerview.getbottom ()-DeltaY/2); }Else{Super. ontouchevent (EV); } Break;default: Break; } } }/** * Activate mobile animation * / Public void Animation() {Translateanimation ta =NewTranslateanimation (0,0,0, Outrect.top-innerview.gettop ()); Ta.setduration ( -);//deceleration changes for better user experienceTa.setinterpolator (NewDecelerateinterpolator ()); Ta.setanimationlistener (NewAnimation.animationlistener () {@Override Public void Onanimationstart(Animation Animation) {animationfinish =false; }@Override Public void onanimationrepeat(Animation Animation) { }@Override Public void Onanimationend(Animation Animation) {innerview.clearanimation ();//Set Innerview back to normal layout positionInnerview.layout (Outrect.left, Outrect.top, Outrect.right, Outrect.bottom); Outrect.setempty (); Animationfinish =true; } }); Innerview.startanimation (TA); }/** * Do I need to turn on animation * / Public Boolean isneedanimation() {return!outrect.isempty (); }/** * Do I need to move the layout * * Public Boolean Isneedmove() {intoffset = innerview.getmeasuredheight ()-getheight (); offset = (Offset <0) ?0: offset;intscrolly = getscrolly ();return(offset = =0|| scrolly = = offset); }}
Other Notes
The following are the inheritance relationships:
ElasticScrollView extends ScrollView
ScrollView extends FrameLayout
FrameLayout extends ViewGroup
ViewGroup extends View
Solve the child control intercept the code of the slide listener onInterceptTouchEvent() ,
By listening to the change of Y, we can determine whether to click on the child control or pull down
getMeasuredHeight()The original measurement height is returned, regardless of the screen,
getHeight()Returns the height that is displayed on the screen.
In fact, when the screen can wrap the content, their values are equal, only when the view screen is out of the way to see their differences. When the screen is exceeded, it getMeasuredHeight() is equal to getHeight() the height that is not displayed outside the screen.
getScrollY()The top of the slide view Display section is returned
Android principle-Rebound ScrollView