手指所在布局位置查询及拖拽块异常变色问题技术咨询
关于Android拖拽操作的两个问题解答
1. 如何获取手指所在的布局位置?
获取手指位置分两种场景,要看你是在触摸事件还是拖拽事件里处理:
触摸事件(OnTouchListener):
在onTouch(View v, MotionEvent event)方法中,你可以用:event.getX()/event.getY():获取相对于当前View的坐标(以View左上角为原点)event.getRawX()/event.getRawY():获取相对于屏幕左上角的绝对坐标
如果需要转换为某个父布局内的坐标,可以先通过父布局的getLocationOnScreen(int[] outLocation)拿到它在屏幕上的位置,再用绝对坐标减去父布局的坐标得到相对位置。
拖拽事件(DragListener):
在onDrag(View v, DragEvent event)方法中,直接调用event.getX()/event.getY()就能拿到拖拽点相对于当前接收事件的View的坐标;同样用event.getRawX()/event.getRawY()获取屏幕绝对坐标。
2. 实现拖拽时单元格变色、放置仅着色被拖拽块的逻辑
从你的描述和代码片段来看,问题出在放置(ACTION_DROP)时的逻辑错误——你可能误把所有单元格或者父布局的背景改成了品红色,而不是只修改被拖拽的块。下面是修正后的完整逻辑:
首先,确保每个单元格View都设置了DragListener,并且拖拽开始时把被拖拽的View通过startDragAndDrop()的localState参数传进去(比如view.startDragAndDrop(clipData, dragShadowBuilder, view, 0),第三个参数就是被拖拽的View本身)。
然后修改onDrag方法:
public boolean onDrag(View v, DragEvent event) { int action = event.getAction(); switch (action) { case DragEvent.ACTION_DRAG_STARTED: // 检查是否接受拖拽事件,这里根据你的mime类型判断,返回true才会接收后续事件 return event.getClipDescription().hasMimeType(ClipDescription.MIMETYPE_TEXT_PLAIN); case DragEvent.ACTION_DRAG_ENTERED: // 手指进入当前单元格,设为黄色 v.setBackgroundColor(Color.YELLOW); return true; case DragEvent.ACTION_DRAG_EXITED: // 手指退出当前单元格,恢复灰色 v.setBackgroundColor(Color.GRAY); return true; case DragEvent.ACTION_DROP: // 获取被拖拽的View(就是startDrag时传的localState) View draggedBlock = (View) event.getLocalState(); // 仅给这个被拖拽的块设置品红色 draggedBlock.setBackgroundColor(Color.MAGENTA); // 处理块的放置逻辑(比如把它添加到当前单元格的容器里) ViewGroup targetContainer = (ViewGroup) v; // 先从原父布局移除 ViewGroup originalParent = (ViewGroup) draggedBlock.getParent(); if (originalParent != null) { originalParent.removeView(draggedBlock); } // 添加到目标单元格 targetContainer.addView(draggedBlock); return true; case DragEvent.ACTION_DRAG_ENDED: // 拖拽结束后,把当前单元格恢复灰色(防止某些场景下没触发EXITED) v.setBackgroundColor(Color.GRAY); return true; default: return false; } }
关键注意点:
- ACTION_DROP时操作的是被拖拽的View:通过
event.getLocalState()拿到拖拽开始时传入的块View,只修改它的背景色,而不是当前单元格或其他区域。 - 拖拽结束时清理状态:在
ACTION_DRAG_ENDED里把单元格恢复灰色,避免因为某些异常情况(比如拖拽到屏幕外)导致单元格停留在黄色。 - 确保startDrag时传入正确的localState:这是能拿到被拖拽View的关键,如果你之前没传,一定要补上。
内容的提问来源于stack exchange,提问作者serkanhelvacioglu
相关产品推荐
相关产品推荐

