A new animation named SpringAnimation has been added to Support Library 25.3.0. If you use it to do a slide control pull back effect, should be good.

SpringAnimation

Before you start, don’t forget to add the following to your app’s build.gradle:

The compile ‘com. Android. Support: appcompat – v7:25.3.0’ compile ‘com. Android. Support: design: 25.3.0’ compile ‘com. Android. Support: support – dynamic – animation: 25.3.0’

Then let’s look at the basic uses of SpringAnimation, starting with its constructor:

public SpringAnimation(View v, ViewProperty property, float finalPosition) {
    super(v, property);
    mSpring = new SpringForce(finalPosition);
    setSpringThreshold();
}Copy the code

You can guess the meaning of the parameter by looking at the name:

  • V – The control to animate
  • Property – The property of the animation, which can be panned, scaled, rotated, etc
  • FinalPosition – The coordinate offset of the control’s position at the end of the animation

The slider implemented here slides up and down, so we get the SpringAnimation like this:

springAnim = new SpringAnimation(this, SpringAnimation.TRANSLATION_X, 0);Copy the code

There are two important properties in SpringAnimation:

  • A higher value bounces faster and is similar to the Stiffness factor. The default value is 1500F
  • DampingRatio – damping: The lower the value, the more times the animation returns after the bounce, the more “DUANG” it feels. The default value is 0.5F

through

springAnim.getSpring().setStiffness(float stiffness)Copy the code

and

springAnim.getSpring().setDampingRatio(float dampingRatio)Copy the code

To set the above two properties.

Call springim.start () again to start the animation.

SpringScrollViewion

We’ll create a SpringScrollView that inherits NestedScrollView and override onTouchEvent to make it bounce back:

@Override
public boolean onTouchEvent(MotionEvent e) {
    switch (e.getAction()) {
        case MotionEvent.ACTION_MOVE:
            if (getScrollY() <= 0) {
                // Top drop down
                if (startDragY == 0) {
                    startDragY = e.getRawY();
                }
                if (e.getRawY() - startDragY > 0) {
                    setTranslationY((e.getRawY() - startDragY) / 3);
                    return true;
                } else {
                    springAnim.cancel();
                    setTranslationY(0); }}break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            if(getTranslationY() ! =0) {
                springAnim.start();
            }
            startDragY = 0;
            break;
    }
    return super.onTouchEvent(e);
}Copy the code

Just a quick explanation.

When the ScrollView is at the top, record the y position of the finger. Set a longitudinal offset to the ScrollView at the top and when sliding down. The reason for dividing by 3 is to make the control feel like it has to be dragged with force.

If you slide up at the top, unanimate the animation and restore the control position, otherwise the control may always be offset.

Finally, when the finger is lifted, perform the spring animation.

Why getRawY() is used here to get coordinates instead of getY()? Because getY() is relative to the coordinate of the control, when TranslationY is set, its value will change, that is, the value of getY() is discontinuous during sliding, and the phenomenon of lag will occur. Whereas getRawY() is the position relative to the screen, the screen is fixed no matter how your controls move.

The drop back effect is done. Oh, by the way, let’s do the bottom pull back as well. Since ScrollView has only one child layout, it can pass

getScrollY() + getHeight()) >= getChildAt(0).getMeasuredHeight()Copy the code

See if it slides to the bottom.

The complete code is as follows:

public class SpringScrollView extends NestedScrollView {

    private float startDragY;
    private SpringAnimation springAnim;

    public SpringScrollView(Context context) {
        this(context, null);
    }

    public SpringScrollView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public SpringScrollView(Context context, @Nullable AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        springAnim = new SpringAnimation(this, SpringAnimation.TRANSLATION_Y, 0);
        // The higher the stiffness is, the faster the rebound will be
        springAnim.getSpring().setStiffness(800.0 f);
        // The smaller the damping default value of 0.5, the more back-and-forth times after rebound
        springAnim.getSpring().setDampingRatio(0.50 f);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        switch (e.getAction()) {
            case MotionEvent.ACTION_MOVE:
                if (getScrollY() <= 0) {
                    // Top drop down
                    if (startDragY == 0) {
                        startDragY = e.getRawY();
                    }
                    if (e.getRawY() - startDragY > 0) {
                        setTranslationY((e.getRawY() - startDragY) / 3);
                        return true;
                    } else {
                        springAnim.cancel();
                        setTranslationY(0); }}else if ((getScrollY() + getHeight()) >= getChildAt(0).getMeasuredHeight()) {
                    // Bottom pull up
                    if (startDragY == 0) {
                        startDragY = e.getRawY();
                    }
                    if (e.getRawY() - startDragY < 0) {
                        setTranslationY((e.getRawY() - startDragY) / 3);
                        return true;
                    } else {
                        springAnim.cancel();
                        setTranslationY(0); }}break;
            case MotionEvent.ACTION_UP:
            case MotionEvent.ACTION_CANCEL:
                if(getTranslationY() ! =0) {
                    springAnim.start();
                }
                startDragY = 0;
                break;
        }
        return super.onTouchEvent(e); }}Copy the code

Finally, look at the results:





The same idea can be applied to other sliders.

No problem.

The source address