Android仿IOS有弹性ScrollView

最近项目里用到了一个开源的仿IOS可弹动的ScrollView,看源代码时发现其实实现原理是用 View动画实现的,每次都播一个动画,最后重新layout这个布局。看到使用了View动画,就有点不想用这个控件了,因为个人感觉View动画,应该是要被淘汰的技术了,于是就自己根据实现原理,重写了一个ScrollView,实现了同样的功能.
思路:利用属性动画,及其View的偏移原理即可实现同样的功能。
代码如下:
/** 
* @description 仿IOS有弹性ScrollView
* @author rzq
* @date 2015年9月19日
*/
public class OverScrollView extends ScrollView
{
    /**
     * 动画执行时间
     */
    private static final int ANIM_DURING = 300;

    /**
     * 最大可拖拽距离 
     */
    private static final int MAX_SPAN = 500;

    private View mContentView;
    private TimeInterpolator mInterpolator;
    /**
     * 是否可上下拉
     */
    private boolean canPullDown;
    private boolean canPullUp;
    private float mDownY;
    private boolean isMove;

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

    public OverScrollView(Context context, AttributeSet attrs)
    {
        super(context, attrs);
    }

    @Override
    protected void onFinishInflate()
    {
        if (getChildCount() > 0)
        {
            mContentView = getChildAt(0);
        }
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev)
    {
        switch (ev.getAction())
        {
        case MotionEvent.ACTION_DOWN:
            mDownY = ev.getY();
            canPullDown = isCanPullDown();
            canPullUp = isCanPullUp();
            break;
        case MotionEvent.ACTION_MOVE:
            float moveY = ev.getY();
            float deltaY = moveY - mDownY;
            if (deltaY > 10 && canPullDown)
            {
                if (deltaY >= MAX_SPAN)
                {
                    deltaY = MAX_SPAN;
                }
                mContentView.setTranslationY(deltaY);
                isMove = true;
            }
            if (deltaY < -10 && canPullUp)
            {
                if (deltaY <= -MAX_SPAN)
                {
                    deltaY = -MAX_SPAN;
                }
                mContentView.setTranslationY(deltaY);
                isMove = true;
            }
            break;
        case MotionEvent.ACTION_UP:
        case MotionEvent.ACTION_CANCEL:
            /**
             * 利用动画回到原位置
             */
            if (isMove)
            {
                scrollToOrginial();
            }
            isMove = false;
            break;
        }
        return super.dispatchTouchEvent(ev);
    }

    /**
     * 利用属性动画滚回原位置 
     */
    private void scrollToOrginial()
    {
        ObjectAnimator anim = ObjectAnimator.ofFloat(mContentView, "translationY", mContentView.getTranslationY(), 0);
        anim.setDuration(ANIM_DURING);
        if (mInterpolator != null)
        {
            anim.setInterpolator(mInterpolator);
        }
        anim.start();
    }

    /**
     * 设置动画差值器 
     */
    public void setInterpolator(TimeInterpolator interpolator)
    {
        this.mInterpolator = interpolator;
    }

    private boolean isCanPullDown()
    {
        return getScrollY() == 0 || mContentView.getHeight() < getHeight() + getScrollY();
    }

    private boolean isCanPullUp()
    {
        return mContentView.getHeight() <= getHeight() + getScrollY();
    }
}

用法与普通的ScrollView用法完全一样,类中属性都是用的默认值,如果想动态修改,可以改我自定义属性使用即可。将代码拷贝到项目中即可。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/lcq5211314123/article/details/48577161