android 长按缩放拖动_自定义可长按拖动View的那些坑

本文介绍了在Android中实现一个可长按拖动的悬浮View的需求,通过分析添加到DecorView的困难和使用WindowManager的解决方案,详细讲解了如何设置窗口参数、处理拖动事件以及避免事件冲突的问题,最终实现了一个简洁的拖动效果。
摘要由CSDN通过智能技术生成

话不多说,先看效果:

自定义可拖动View

前两天碰见一个需求,效果如图。需要在当前actvity内实现一个可拖动控制的悬浮view。

这不是都快被造烂的轮子吗,我想都没想去github上一顿搜,然后很快啊就找到了。细看了一下才发现是自己大意了。github上的实现过于复杂了,我这里只需要在当前activity内生效,并不需要做一个跨多个activity页面甚至跨app能显示的悬浮view,于是决定自己造轮子。

思考:首先想到的一个方案是,把悬浮view直接添加到activity的根view中,也就是DecorView中。但是实际动手才发现在我们的项目中很难落地,因为我们主activity承担了太多业务,很多view会在某种操作后动态的被添加进来,导致很难保证悬浮view始终处于最上方(这里可以监听view树,当树结构的时候控制悬浮view始终显示在最上层,但逻辑会稍显复杂,并且可能会造成悬浮view在拖动过程中的中端或卡顿)。既然不能直接把悬浮view添加进viewGroup中,那只能借助于activity的windowManager了。一个activity可以展示多种类型的window,这里需要根据需求的具体情况而定选用什么类型,一般来说SUB_WINDOW的类型是够用了(也有例外,比如activity中包含了surfaceView,因为surfaceView在当前窗口中的类型也是SUB_WINDOW,因此会造成surfaceView覆盖悬浮view的情况)。这样的话悬浮view本身单独处在一个window中,android的事件是不能跨window传递的——至少framework层不支持这样的操作,为了不影响用户和activity主界面的交互,悬浮view所在的窗口大小只能是WRAP_CONTENT。一般来说还需要将窗口设计为透明的,核心代码如下:

mWindowManager = (WindowManager) activity.getSystemService(Context.WINDOW_SERVICE);

mLayoutParams =new WindowManager.LayoutParams();

mLayoutParams.flags = WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE |

WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH |

WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS |

WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL;

mLayoutParams.width = WindowManager.LayoutParams.WRAP_CONTENT;

mLayoutParams.height = WindowManager.LayoutParams.WRAP_CONTENT;

mLayoutParams.type = WindowManager.LayoutParams.LAST_SUB_WINDOW;

mLayoutParams.format = PixelFormat.RGBA_8888;

mLayoutParams.gravity = Gravity.TOP | Gravity.START;

这样的话拖动效果只能是移动窗口的位置了,如果只移动view的位置,你会神奇的发现view被你移出窗口之外了。

核心代码如下:

mLayoutParams.x = xPos;

mLayoutParams.y = yPos;

mWindowManager.updateViewLayout(mView, mLayoutParams);

另外在拖动的时候要注意去抖动,还要注意触发点击事件不要被拖动影响。这种代码网上比比皆是,就不贴了,开此博客的目的主要是记录解决问题的思路。

实现完毕,美滋滋。又可以去撩产品妹子了~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值