You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

手指所在布局位置查询及拖拽块异常变色问题技术咨询

关于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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 11:00:50