`

使用SpringAnimation实现带下拉弹簧动画的 ScrollView

 
阅读更多
在刚推出的 Support Library 25.3.0 里面新增了一个叫 SpringAnimation 的动画,也就是弹簧动画。要是用它来做一个滑动控件下拉回弹的效果,应该不错吧。

SpringAnimation
开始之前,别忘了在 app 的 build.gradle 加上:

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'

然后我们看看 SpringAnimation 的基本用法,首先是它的构造方法:

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

看命名可以大概猜到参数的意义了:

v - 要执行动画的控件
property - 动画的性质,可以选择平移、缩放、旋转等
finalPosition - 动画结束时,控件所在位置的坐标偏移量
这里实现的滑动控件是上下滑动的,所以我们这样来获取 SpringAnimation :

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

SpringAnimation 里面有两个比较重要的属性,分别是:

Stiffness - 刚度,值越大回弹的速度越快,类似于劲度系数,默认值是 1500f
DampingRatio - 阻尼,值越小,回弹后,动画来回的次数越多,就是更有「DUANG」的感觉,默认值是 0.5f
通过

springAnim.getSpring().setStiffness(float stiffness)



springAnim.getSpring().setDampingRatio(float dampingRatio)

来设置上面两个属性。

再调用 springAnim.start() 就可以开始动画啦。

SpringScrollViewion
我们自定义一个 SpringScrollView 继承 NestedScrollView,重写 onTouchEvent 方法让它有回弹的效果:

@Override
public boolean onTouchEvent(MotionEvent e) {
    switch (e.getAction()) {
        case MotionEvent.ACTION_MOVE:
            if (getScrollY() <= 0) {
                //顶部下拉
                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);
}

简单解释一下哈。

当 ScrollView 在顶部时,记录下手指所在的 y 轴位置。在顶部并且是往下滑动的时候,给 ScrollView 设置一个纵向的偏移。之所以除以 3,是为了让控件有种要用力才能拖动的感觉。

在顶部的时候如果是往上滑动,则把动画效果取消,把控件位置复原,否则可能出现控件一直偏移的情况。

最后当手指抬起时,执行弹簧动画就好了。

为什么这里用 getRawY() 获取坐标,而不是用 getY() 来获取。因为 getY() 是相对于控件的坐标,当设置了 TranslationY 之后会改变它的值,也就是在滑动的时候 getY() 的值是不连续的,会出现卡顿的现象。而 getRawY() 是相对于屏幕的位置,管你控件怎么动,屏幕都是固定的。

下拉回弹的效果就已经完成了。对了,我们顺便把底部上拉的回弹也做一下呗。由于ScrollView只有一个子布局,所以可以通过

getScrollY() + getHeight()) >= getChildAt(0).getMeasuredHeight()

判断是否滑动到了底部。

完整代码如下:

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);
        //刚度 默认1200 值越大回弹的速度越快
        springAnim.getSpring().setStiffness(800.0f);
        //阻尼 默认0.5 值越小,回弹之后来回的次数越多
        springAnim.getSpring().setDampingRatio(0.50f);
    }

    @Override
    public boolean onTouchEvent(MotionEvent e) {
        switch (e.getAction()) {
            case MotionEvent.ACTION_MOVE:
                if (getScrollY() <= 0) {
                    //顶部下拉
                    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()) {
                    //底部上拉
                    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);
    }

}


同样的思路也可以用在别的滑动控件里面。

https://github.com/SouthernBox/SpringScrollView


SpringAnimation详解
http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/0330/7757.html
分享到:
评论

相关推荐

    ScrollView实现下拉刷新

    "ScrollView实现下拉刷新"这个主题聚焦于如何在滚动视图中添加一个下拉刷新功能,这通常用于列表或者网格视图,使得用户可以更新内容而无需离开当前页面。这种特性在许多应用程序中非常常见,比如社交媒体应用和新闻...

    解决Scrollview嵌套listview下拉刷新的一些问题

    当在一个ScrollView中嵌套一个ListView时,可能会遇到一些特定的问题,尤其是在实现下拉刷新功能时。本文将深入探讨这些问题及其解决方案。 ### 问题1:滑动冲突 由于ScrollView和ListView都具有滚动功能,它们之间...

    比较好用的弹性和下拉刷新的ScrollView

    例如,我们可以使用SwipeRefreshLayout配合自定义的RecyclerView或ScrollView来实现下拉刷新功能。首先,添加SwipeRefreshLayout作为外层布局,然后将ScrollView或RecyclerView作为其子视图。设置好监听器后,当用户...

    下拉回弹的ScrollView

    总的来说,实现"下拉回弹的ScrollView"需要对Android的视图系统、触摸事件处理、动画框架有深入的理解,并且需要通过巧妙的算法设计来模拟真实的物理行为。这种自定义视图的开发对于提升APP的用户体验具有重要意义,...

    下拉刷新scrollview

    不同于ListView,ScrollView没有内置的下拉刷新功能,因此需要我们自己实现。下面我们将详细探讨如何为ScrollView添加下拉刷新功能,以及如何实现自定义头部。 一、下拉刷新原理 下拉刷新的核心在于监听用户的滑动...

    安卓scrollview动画滚动到顶部

    本文将深入探讨如何实现一个ScrollView动画滚动到顶部的功能,这在很多应用场景中都非常有用,例如用户需要回到页面顶部查看新的信息或者刷新内容。 首先,我们需要了解ScrollView的基本用法。ScrollView是...

    使用ScrollView实现ListView下拉刷新示例工程

    最近写了一个ScrollView中嵌套ListView实现下拉刷新的Demo, 相关blog 为: http://blog.csdn.net/u013015161/article/details/45680037

    scrollView实现下拉刷新

    "ScrollView实现下拉刷新"这个主题主要关注如何在ScrollView中添加一个自定义视图来实现下拉刷新的功能。这个功能常见于许多应用的顶部,当用户下拉时,会触发数据的更新或加载更多内容。 首先,我们来详细了解一下...

    android ScrollView顶部使用Viewpager的轮播图,下拉图片能放大效果

    本文将详细讲解如何在ScrollView中实现顶部使用ViewPager的轮播图,并且在下拉时图片能产生放大效果。这个功能的实现涉及到了Android的布局管理、动画效果以及自定义控件等多个知识点。 首先,我们来分析需求。标题...

    PullToRefresh使用详解(五)--下拉刷新的ScrollView ---源码

    博客《PullToRefresh使用详解(五)--下拉刷新的ScrollView》对应源码,博客地址:http://blog.csdn.net/harvic880925/article/details/24722657

    自定义动画框架实现ScrollView滚动动画

    为了在ScrollView中添加滚动动画,我们需要监听ScrollView的滚动事件,这可以通过重写`onScrollChanged()`方法或者使用`OnScrollChangeListener`接口来实现。 接着,我们来构建自定义动画框架的基础。一个简单的...

    下拉刷新ScrollView

    本资源提供的就是一个实现了下拉刷新功能的ScrollView,代码结构清晰,注释详尽,对于开发者来说是一个很好的学习和参考实例。 下拉刷新的核心概念是UIRefreshControl,它是iOS SDK提供的一种原生控件,用于添加到...

    scrollview下拉放大效果,弹回效果动画(基于手势,不导入第三方包)

    弹回效果通常是通过动画实现的,可以使用ValueAnimator或者ObjectAnimator。在手指离开屏幕后,我们创建一个动画,让视图逐渐恢复到原始位置。以下是一个使用ObjectAnimator的例子: ```java private void ...

    ScrollView 实现下拉刷新

    在许多应用中,为了提供更好的用户体验,我们常常需要在ScrollView中实现下拉刷新的功能,这样用户可以轻松获取最新的数据而无需离开当前界面。本篇文章将深入探讨如何在ScrollView中实现下拉刷新。 首先,我们需要...

    个人中心下拉弹回scrollview

    总结来说,"个人中心下拉弹回scrollview"是一个通过自定义`ScrollView`实现的交互效果,它涉及到Android触摸事件处理、动画系统以及弹性物理模型的应用。通过这样的设计,开发者可以为用户提供更加生动有趣的界面...

    android scrollview 下拉刷新

    如果需要自定义,可以通过设置颜色或者更换其他动画实现。 5. 如果不想使用SwipeRefreshLayout,还可以考虑自定义ScrollView,重写其滚动事件,监听上滑并处理刷新逻辑。这种方法更复杂,但能提供更大的定制空间。 ...

    安卓下拉上拉刷新相关-百行代码搞定下拉刷新通过继承ScrollView编写.zip

    本教程将介绍如何通过继承ScrollView来实现一个简单的下拉刷新功能,适用于初学者理解基本原理和动手实践。 首先,我们来看"PullToRefresh"这个文件,它是实现下拉刷新的核心部分。在Android中,下拉刷新通常涉及到...

    ScrollView下拉刷新

    综上所述,实现ScrollView的下拉刷新功能需要理解SwipeRefreshLayout的工作原理,处理好嵌套滚动,编写合适的数据加载逻辑,并关注用户体验和错误处理。通过这些技术,开发者可以为用户创建更加互动和动态的界面。

    ios-动画scrollView.zip

    这个“ios-动画scrollView.zip”文件可能包含了一些示例代码和资源,用于展示如何在ScrollView中实现动画效果,以及可能的自定义Segment控件的使用。 首先,我们来了解一下在ScrollView中添加动画的基本概念。通常...

Global site tag (gtag.js) - Google Analytics