Android回弹阻尼效果的简单实现,非基于ListView,ScrollView.

原创 cheny  2016-12-23 23:26  阅读 81 次 评论 0 条

好久没有写Android博客了,这段时间有点浮躁,静不下心来写。趁今天周五心情好点,写个简单点的技术实现。

先简单说说回弹阻尼效果的思路,先自定义一个ViewGroup ----- ReboundEffectsView,通过手势的上下滑动距离差不断改变其子View(一般都是子ViewGroup)的相对于该ReboundEffectsView的位置(坐标),当手势为释放(action_up)或取消(action_cancel)时,重置子View最初始相对ReboundEffectsView的位置,最初始的位置值应在处理滑动事件前保存下来以用来重置。

Android回弹阻尼效果的简单实现,非基于ListView,ScrollView. Android 第1张

 Demo项目下载地址:https://github.com/ausboyue/ReboundEffects

 

进入代码板块:

在自定义ReboundEffectsView中重写onFinishInflate方法,XML布局完成加载后获取其第一个子View(使用该ReboundEffectsView时应保证其只有且只有一个子View,唯一的独生子,我就叫它太子View):

    /**
     * XML布局完成加载
     */
    @Override
    protected void onFinishInflate() {
        super.onFinishInflate();
        if (getChildCount() > 0) {
            mPrinceView = getChildAt(0);// 获得子View,太子View
        }
    }

onTouchEvent方法,分别对ACTION_DOWN,ACTION_MOVE,ACTION_UP,ACTION_CANCEL事件进行处理:

    /**
     * Touch事件
     */
    @Override
    public boolean onTouchEvent(MotionEvent e) {
        if (null != mPrinceView) {
            switch (e.getAction()) {
            case MotionEvent.ACTION_DOWN:
                onActionDown(e);
                break;
            case MotionEvent.ACTION_MOVE:
                return onActionMove(e);

            case MotionEvent.ACTION_UP:
                onActionUp(e);
                break;
            case MotionEvent.ACTION_CANCEL:
                onActionUp(e);// 当ACTION_UP一样处理
                break;
            }
        }
        return super.onTouchEvent(e);
    }

onActionDown中保存子View的初始上下高度位置:

    /**
     * 手指按下事件
     */
    private void onActionDown(MotionEvent e) {
        mVariableY = e.getY();
        /**
         * 保存mPrinceView的初始上下高度位置
         */
        mInitTop = mPrinceView.getTop();
        mInitBottom = mPrinceView.getBottom();
    }

核心代码,onActionMove中,主要是判断手势移动事件是否为上下滑动事件,是的话根据上下滑动的绝对距离重绘子View的位置(这里的绝对距离除以3了,目的是放缓子View的移动速度),并在以后的Touch拿到直接的控制权,返回true。

    /**
     * 手指滑动事件
     */
    private boolean onActionMove(MotionEvent e) {
        float nowY = e.getY();
        float diff = (nowY - mVariableY) / 3;
        if (Math.abs(diff) > 0) {// 上下滑动
            // 移动太子View的上下位置
            mPrinceView.layout(mPrinceView.getLeft(), mPrinceView.getTop() + (int) diff, mPrinceView.getRight(),
                    mPrinceView.getBottom() + (int) diff);
            mVariableY = nowY;
            isEndwiseSlide = true;
            return true;// 消费touch事件
        }
        return super.onTouchEvent(e);
    }

手指释放或手势取消时,则调用onActionUp方法恢复子View的位置:

    /**
     * 手指释放事件
     */
    private void onActionUp(MotionEvent e) {
        if (isEndwiseSlide) {// 是否为纵向滑动事件
            // 是纵向滑动事件,需要给太子View重置位置
            resetPrinceView();
            isEndwiseSlide = false;
        }
    }

    /**
     * 回弹,重置太子View初始的位置
     */
    private void resetPrinceView() {
        mPrinceView.layout(mPrinceView.getLeft(), mInitTop, mPrinceView.getRight(), mInitBottom);
    }

 

OK,整个自定义View中重写原生的方法并不多,也不需要自行测量和绘制View,代码逻辑也足够精简,如果有什么bug或建议可以在下面评论,我会继续更新博客。

 

 

本文地址:https://www.icheny.cn/android%e5%9b%9e%e5%bc%b9%e9%98%bb%e5%b0%bc%e6%95%88%e6%9e%9c%e7%9a%84%e7%ae%80%e5%8d%95%e5%ae%9e%e7%8e%b0%e9%9d%9e%e5%9f%ba%e4%ba%8elistviewscrollview/
关注我们:加我微信:扫描二维码乘月网的微信号,微信号:ausboyue
版权声明:本文为原创文章,版权归 cheny 所有,欢迎分享本文,转载请保留出处!

发表评论


表情