笔记 android悬浮窗的拖动实现踩坑

81 篇文章 3 订阅
16 篇文章 1 订阅

想要实现一个可拖动的悬浮窗,原理上非常简单:根据action_move时的event坐标偏移,去修改view的位置即可。
但是实际实现上踩了个小坑。

详细踩坑:

平时获取event的坐标,都是用event.getX() 和 event.getY() ,但是实操下来发现,这样会导致拖动效果不跟手, 拖动的位置比手势移动的位置要小,并且会有明显的位置抖动。

在这个拖动的场景下,其实应该使用 event.getRawX() 和 event.getRawY() 来获取坐标。

event.getX() 和 event.getRawX() 的区别:

    /**
     * {@link #getX(int)} for the first pointer index (may be an
     * arbitrary pointer identifier).
     *
     * @see #AXIS_X
     */
    public final float getX() {
        return nativeGetAxisValue(mNativePtr, AXIS_X, 0, HISTORY_CURRENT);
    }
    /**
     * Returns the original raw X coordinate of this event.  For touch
     * events on the screen, this is the original location of the event
     * on the screen, before it had been adjusted for the containing window
     * and views.
     *
     * @see #getX(int)
     * @see #AXIS_X
     */
    public final float getRawX() {
        return nativeGetRawAxisValue(mNativePtr, AXIS_X, 0, HISTORY_CURRENT);
    }

getRawX()使用的是相对屏幕的坐标,而 getX()使用的是相对view的坐标,在view本身随手势移动的时候,这个相对view的坐标就会发生错误的偏移,导致拖动效果不跟手。

实际代码

binding.root.setOnTouchListener(object : View.OnTouchListener {
                var xDown = 0f
                var yDown = 0f

                var interactorTranslationXWhenDown = 0f
                var interactorTranslationYWhenDown = 0f

                override fun onTouch(v: View?, event: MotionEvent): Boolean {
                    when (event.action) {
                        MotionEvent.ACTION_DOWN -> {
                            xDown = event.rawX
                            yDown = event.rawY
                            interactorTranslationXWhenDown = interactorTranslationX
                            interactorTranslationYWhenDown = interactorTranslationY
                        }
                        MotionEvent.ACTION_MOVE -> {
                            val dx = event.rawX - xDown
                            val dy = event.rawY - yDown
                            interactorTranslationX =
                                interactorTranslationXWhenDown + dx
                            interactorTranslationY =
                                interactorTranslationYWhenDown + dy
                            Timber.e("dx:${dx} dy:${dy}")
                            updateTranslation()
                        }
                        else -> {}
                    }
                    return false
                }

            })

注:如果想写的简单一点,也可以直接使用

interactorTranslationX = event.rawX
interactorTranslationY = event.rawY

这样也能实现基本的拖动效果,只是view会跳到手指右下角的位置来拖动,有点难用。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值