Android 实现可拖动、吸附左右边界的悬浮框

11 篇文章 1 订阅

实现思路:

  • 创建拖动范围和拖动控件
  • 实现拖动控件的可拖动效果,通过OnTouchListener实现
  • 限制拖动范围为边界
  • 实现左右两边停靠,并添加动画返回效果

首先实现可拖动的功能:

dragView.setOnTouchListener(new OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        lastX = (int) event.getRawX();
                        lastY = (int) event.getRawY();
                        break;
                    case MotionEvent.ACTION_MOVE:
                        int mTop = dragView.getTop();
                        int mLeft = dragView.getLeft();
                        int mBottom = dragView.getBottom();
                        int mRight = dragView.getRight();

                        //X轴拖动的距离
                        int slideX = (int) (event.getRawX() - lastX);
                        //Y轴拖动的距离
                        int slideY = (int) (event.getRawY() - lastY);

                        if (mTop < 0) {
                            mTop = 0;
                            mBottom = dragView.getHeight();
                        }

                        int rootHeight = getHeight();
                        int rootWidth = getWidth();

                        //为上下左右做边界限制
                        if (mBottom > rootHeight) {
                            mBottom = rootHeight;
                            mTop = rootHeight - dragView.getHeight();
                        }
                        //这里的hideSize为隐藏到边界外的部分,设置为0则悬浮框完整显示
                        if (mLeft < -hideSize) {
                            mLeft = -hideSize;
                            mRight = dragView.getWidth() - hideSize;
                        }

                        if (mRight > rootWidth + hideSize) {
                            mRight = rootWidth + hideSize;
                            mLeft = rootWidth - dragView.getWidth() + hideSize;
                        }

                        dragView.layout(mLeft + slideX, mTop + slideY, mRight + slideX, mBottom + slideY);
                        lastX = (int) event.getRawX();
                        lastY = (int) event.getRawY();
                        break;

然后再在拖动结束之后判断位置 向左右移动

case MotionEvent.ACTION_UP:
                        int leftLimit = (getWidth() - dragView.getWidth()) / 2;
                        //在最中间的时候动画所需最大执行时间
                        int maxDuration = 500;
                        int duration;
                        if (dragView.getLeft() < leftLimit) {
                            //根据距离边界的距离,弹性计算动画执行时间,防止距离边界很近的时候执行时间仍是过长
                            duration = maxDuration * (dragView.getLeft() + hideSize) / (leftLimit + hideSize);
                            animSlide(dragView, dragView.getLeft(), -hideSize, duration);
                        } else {
                            duration = maxDuration * (getWidth() + hideSize - dragView.getRight()) / (leftLimit + hideSize);
                            animSlide(dragView, dragView.getLeft(), getWidth() - dragView.getWidth() + hideSize, duration);
                        }
                        break;

滑动增加动画效果

private void animSlide(final View view, final int leftFrom, int leftTo, int duration) {
        ValueAnimator valueAnimator = ValueAnimator.ofInt(leftFrom, leftTo);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                int viewLeft = (int) valueAnimator.getAnimatedValue();
                view.layout(viewLeft, view.getTop(), viewLeft + view.getWidth(), view.getBottom());
            }
        });
        //为防止溢出边界时,duration时间为负值,做下0判断
        valueAnimator.setDuration(duration < 0 ? 0 : duration);
        valueAnimator.start();
    }

直接代码,好使给个star谢谢

完整代码:https://github.com/MyUserNameHSW/AdsorptionView

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值