ScrollView实现阻尼回弹效果!

今天跟大伙简绍个ScrollView的阻尼回弹!下拉到一定程度,可以回调进行刷新和进行操作等!
直接上代码了!

package com.***.fb**.widget;

import android.content.Context;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
import android.view.animation.Animation;
import android.view.animation.TranslateAnimation;
import android.widget.ScrollView;

/**
 * @类名:BounceScrollView
 * @类描述:支持上下反弹效果的ScrollView
 * @作者:Administrator
 */
public class BounceScrollView extends ScrollView {
    private boolean isCalled;
    private Callback mCallback;
    /** 包含的View */
    private View mView;
    /** 存储正常时的位置 */
    private Rect mRect = new Rect();
    /**  y坐标 */
    private int y;
    private boolean isFirst = true;

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

    /**
     * @重写方法名:onFinishInflate
     * @父类:@see android.view.View#onFinishInflate()
     * @方法说明:根据 XML 生成视图工作完成.该函数在生成视图的最后调用,在所有子视图添加完之后. 即使子类覆盖了 onFinishInflate
     * 方法,也应该调用父类的方法,使该方法得以执行.
     */
    @Override
    protected void onFinishInflate() {
        if (getChildCount() > 0)
            mView = getChildAt(0);
        super.onFinishInflate();
    }

    @Override
    public boolean onTouchEvent(MotionEvent ev) {
        if (mView != null) {
            commonOnTouch(ev);
        }
        return super.onTouchEvent(ev);
    }

    private void commonOnTouch(MotionEvent ev) {
        int action = ev.getAction();
        int cy = (int) ev.getY();
        switch (action) {
        case MotionEvent.ACTION_DOWN:
            break;
        /** 跟随手指移动 */
        case MotionEvent.ACTION_MOVE:

            int dy = cy - y;
            if (isFirst) {
                dy = 0;
                isFirst = false;
            }
            y = cy;

            if (isNeedMove()) {
                if (mRect.isEmpty()) {
                    /**  记录移动前的位置 */
                    mRect.set(mView.getLeft(), mView.getTop(),
                            mView.getRight(), mView.getBottom());
                }

                mView.layout(mView.getLeft(), mView.getTop() + 2 * dy / 3,
                        mView.getRight(), mView.getBottom() + 2 * dy / 3);

                if (shouldCallBack(dy)) {
                    if (mCallback != null) {
                        if (!isCalled) {
                            isCalled = true;
                            resetPosition();
                            mCallback.callback();
                        }
                    }
                }
            }

            break;
        /** 反弹回去 */
        case MotionEvent.ACTION_UP:
            if (!mRect.isEmpty()) {
                resetPosition();
            }
            break;

        }
    }

    /**
     * @方法说明:当从上往下,移动距离达到一半时,回调接口
     * @方法名称:shouldCallBack
     * @param dy
     * @return
     * @返回值:boolean
     */
    private boolean shouldCallBack(int dy) {
        if (dy > 0 && mView.getTop() > getHeight() / 2)
            return true;
        return false;
    }

    /**
     * @方法说明:重置坐标
     * @方法名称:resetPosition
     * @返回值:void
     */
    private void resetPosition() {
        Animation animation = new TranslateAnimation(0, 0, mView.getTop(),
                mRect.top);
        animation.setDuration(200);
        animation.setFillAfter(true);
        mView.startAnimation(animation);
        mView.layout(mRect.left, mRect.top, mRect.right, mRect.bottom);
        mRect.setEmpty();
        isFirst = true;
        isCalled = false;
    }

    /**
     * @方法说明:是否需要移动布局 inner.getMeasuredHeight():获取的是控件的总高度
     * @方法名称:isNeedMove
     * @return,getHeight():获取的是屏幕的高度
     * @返回值:boolean
     */
    public boolean isNeedMove() {
        int offset = mView.getMeasuredHeight() - getHeight();
        int scrollY = getScrollY();
        // 0是顶部,后面那个是底部
        if (scrollY == 0 || scrollY == offset) {
            return true;
        }
        return false;
    }

    /**
     * @方法说明:当scrollView下拉到一定程度后,进行的回调方法
     * @方法名称:setCallBack
     * @param callback
     * @返回值:void
     */
    public void setCallBack(Callback callback) {
        mCallback = callback;
    }

    public interface Callback {
        void callback();
    }
}

在xml文件中

<com.**.***.wid**.BounceScrollView
        android:id="@+id/id_scrollView"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:background="@color/basecolor"
        android:cacheColorHint="@android:color/transparent"
        android:fadingEdge="none"
        android:fillViewport="false"
        android:scrollbars="none" >
        ......
</com.**.***.wid**.BounceScrollView>

在java文件中

        id_scrollView
                .setVerticalScrollBarEnabled(false);
        id_scrollView
                .setHorizontalScrollBarEnabled(false);
        id_scrollView.setCallBack(new Callback() {
            @Override
            public void callback() {
                //这里进行操作,如刷新等
                Tools.showPrompt("刷新成功!", Tools.TOAST_SHOW);
            }
        });

用了很长时间,性能自我感觉不错!特意保存!

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值