Original intention:
In fact, there are many such ScrollView projects on github, but I have to say that there are too many functions and it is too messy. I just want a ScrollView with simple effects, and I just listen to the sliding distance under the monitor. I thought about it and wrote it myself.
Let’s talk about the idea first. If you don’t want to read it, you can skip this step directly and read the following code:
Android native ScrollView does not support pulling out of the screen, and it does not have a rebound effect, but the user-friendliness is not very good, I don’t know why it is not designed so.
What I want to do is as stated above:
1. Hope to pull out of the screen
2. I hope the control rebounds after letting go
My idea is to operate the subView of the ScrollView
All view sliding controls must be controlled by onTouchEvent, so, naturally, the focus I need to pay attention to is the onTouchEvent method.
The rebound effect involves position calculation, and my idea here is to use a simple TranslateAnimation to achieve it.
This is the general idea. First, determine the idea, and then the code is always polished.
Post code:
import ; import ; import ; import ; import ; import ; import ; public class ReboundScrollView extends ScrollView { private static final float MOVE_DELAY = 0.3f;//Drag coefficient when the screen is pulled out private static final int ANIM_TIME = 300;//Bounce time consuming private static final int FLING = 2;//fling coefficient private View childView; private boolean havaMoved; private Rect originalRect = new Rect(); private float startY; @Override protected void onFinishInflate() { (); if (getChildCount() > 0) { childView = getChildAt(0); } } @Override public void fling(int velocityY) { (velocityY / 2); } @Override protected void onLayout(boolean changed, int l, int t, int r, int b) { (changed, l, t, r, b); if (childView == null) return; ((), (), (), ()); } public ReboundScrollView(Context context, AttributeSet attrs, int defStyle) { super(context, attrs, defStyle); } public ReboundScrollView(Context context, AttributeSet attrs) { super(context, attrs); } public ReboundScrollView(Context context) { super(context); } /** * In touch events, handle pull-up and pull-down logic */ @Override public boolean dispatchTouchEvent(MotionEvent ev) { if (childView == null) { return (ev); } int action = (); switch (action) { case MotionEvent.ACTION_DOWN: startY = (); break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (!havaMoved) break; TranslateAnimation anim = new TranslateAnimation(0, 0, (), ); (ANIM_TIME); (anim); // Set the flag position back to false havaMoved = false; resetViewLayout(); break; case MotionEvent.ACTION_MOVE: float nowY = (); int deltaY = (int) (nowY - startY); int offset = (int) (deltaY * MOVE_DELAY); (, + offset, , + offset); havaMoved = true; break; default: break; } return (ev); } public void resetViewLayout() { (, , , ); } }
After posting the code, analyze the specific implementation:
The first is to pull out the screen, and during the MOVE process, for beyond the part of the code, I use layout to reset the position of the child View.
The second thing to achieve is rebound, and you will always come back if you drag it out:
Here I define a Rect, in the onLayout(boolean changed, int l, int t, int r, int b) method, record the initial position of the ScrollView to facilitate resetting the rebound.
I've said a lot, look at the key code in the code
MOVE code:
float nowY = (); int deltaY = (int) (nowY - startY); int offset = (int) (deltaY * MOVE_DELAY); (, + offset, , + offset); havaMoved = true;
This is what you need to do when MotionEvent.ACTION_MOVE. Reset the position of the chlidView, which is the lauout method. This is based on the value of originalRect, and the corresponding sliding coefficient is set, otherwise it will feel too sensitive.
Rebound code:
if (!havaMoved) break; TranslateAnimation anim = new TranslateAnimation(0, 0, (), ); (ANIM_TIME); (anim); // Set the flag position back to false havaMoved = false; resetViewLayout(); ... ... public void resetViewLayout() { (, , , ); }
When you finger MotionEvent.ACTION_UP or MotionEvent.ACTION_CANCEL, put the clipdView in place and set the animation, and this is the rebound.
Replenish:
This is a very simple rebound ScrollView. It should be noted that I have not distinguished between normal movements within the screen and off-screen movements here. In this way, we need to determine whether the current movement needs to be rewritten, that is, whether it is in the pull-up and pull-down part. Without making a judgment, my current code will cause the distance your gestures to move and the distance your control scrolls are different. I feel like you won't notice this if you use it normally. But this kind of demand is not ruled out.
Pulling down is actually not easy to judge, because I am operating ChildView here. GetScrollY() is definitely 0 during the pull-up process of ScrollView, so I haven't thought about this yet. But pulling up is relatively simple. When <= + getScrollY, the click on the screen is pulled up, so this should be figured out.
git address:/cjhandroid/ReboundScrollView
Source code download:http://xiazai./201611/yuanma/androidReboundScrollView().rar
The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.