【发布时间】:2016-07-15 01:52:08
【问题描述】:
我有一个几乎全屏的视图,底部有一个水平 RecyclerView(在自定义视图内)。我正在尝试将元素从 RecyclerView 拖到页面上半部分的视图上。我正在尝试同时监听轻敲和拖动,但大多数时候我无法让触摸监听器返回 ACTION_DOWN 和 ACTION_CANCEL 以外的任何内容。
一个超级烦人的事情是,如果我设置断点并进入调试模式,它工作正常。我得到 ACTION_DOWN -> ACTION_UP -> ACTION_DOWN -> ACTION_UP。有时它在第一次启动时有效,但在那之后它就不起作用了。如果我注释掉 v.startDrag() 行,它可以完美运行,但是我没有得到阴影。
在 onBindViewHolder() 中,我为每个项目设置了一个触摸监听器,如下所示:
tv.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent motionEvent) {
System.out.println(motionEvent.toString());
if (motionEvent.getAction() == MotionEvent.ACTION_DOWN) {
ClipData.Item item = new ClipData.Item(groupId);
String[] clipDescription = {ClipDescription.MIMETYPE_TEXT_PLAIN};
ClipData dragData = new ClipData(groupId), clipDescription, item);
View.DragShadowBuilder shadowBuilder = new DragShadow(v);
v.startDrag(dragData, shadowBuilder, v, 0); //commenting out this line lets me receive actions other than ACTION_CANCEL.
}
return true;
}
});
这是我的 DragShadow 课程。
private class DragShadow extends View.DragShadowBuilder {
View view;
private Point mScaleFactor;
public DragShadow(View view) {
super(view);
this.view = view;
}
@Override
public void onDrawShadow(Canvas canvas) {
canvas.scale(mScaleFactor.x / (float) getView().getWidth(),
mScaleFactor.y / (float) getView().getHeight());
getView().draw(canvas);
}
@Override
public void onProvideShadowMetrics(Point shadowSize,
Point shadowTouchPoint) {
View v = getView();
int height = v.getHeight() * 2;
int width = v.getWidth() * 2;
shadowSize.set(width, height);
mScaleFactor = shadowSize;
shadowTouchPoint.set(width / 2, height / 2);
}
}
如果我在 onTouch 中添加一条日志语句以立即打印 motionEvent 作为第一行,它总是 ACTION_DOWN 紧跟 ACTION_CANCEL。我尝试单击或拖动都没关系:
07-14 18:39:00.699 11560-11560/com.whis.mobilize I/System.out: MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=67.0, y[0]=77.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=109050123, downTime=109050123, deviceId=4, source=0x1002 }
07-14 18:39:00.705 11560-11560/com.whis.mobilize I/System.out: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=277.0, y[0]=1685.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=109050131, downTime=109050123, deviceId=4, source=0x1002 }
07-14 18:39:00.745 11560-11560/com.whis.mobilize I/ViewRootImpl: Reporting drop result: false
07-14 18:39:03.636 11560-11560/com.whis.mobilize I/System.out: MotionEvent { action=ACTION_DOWN, actionButton=0, id[0]=0, x[0]=49.0, y[0]=52.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=109053061, downTime=109053061, deviceId=4, source=0x1002 }
07-14 18:39:03.641 11560-11560/com.whis.mobilize I/System.out: MotionEvent { action=ACTION_CANCEL, actionButton=0, id[0]=0, x[0]=439.0, y[0]=1660.0, toolType[0]=TOOL_TYPE_FINGER, buttonState=0, metaState=0, flags=0x0, edgeFlags=0x0, pointerCount=1, historySize=0, eventTime=109053067, downTime=109053061, deviceId=4, source=0x1002 }
07-14 18:39:03.712 11560-11560/com.whis.mobilize I/ViewRootImpl: Reporting drop result: false
我尝试添加添加 RecyclerView 项目侦听器,到处覆盖 onTouch(),到处添加 requestDisallowInterceptTouchEvent(true),到处覆盖 onInterceptTouchEvent(),但没有任何效果。
我在这里找到了其他类似的问题,但都没有答案:
Draggable View not moving, calls ACTION_DOWN then directly to ACTION_CANCEL
EditText only calling ACTION_DOWN and ACTION_CANCEL sometimes
任何帮助将不胜感激。谢谢!
编辑
今天早上我意识到在记录上面的触摸事件时,ACTION_CANCEL 来自另一个位置。该触摸事件的 x 和 y 值与开始 ACTION_DOWN 的 x 和 y 截然不同。我认为它们对应于 x 和 y,其中拖动的阴影对应于 Activity。但是我仍然无法修复它。
我刚刚完成并添加了 onTouchListeners,它对我在整个层次结构中可以访问的每个视图都返回 false,并且这种行为仍在发生。如果我在我的 Activity 上覆盖 dispatchTouchEvent,事件看起来很好,所以它发生在更下方嵌套的某个地方。
我还禁用了所有动画和下拉刷新,但没有骰子。
【问题讨论】:
-
你说当你评论最后一行时你的问题就消失了是吧?
-
您是在模拟器还是真实设备上使用它?有时我在拖动模拟器时遇到问题。
-
@Elltz 是的,这绝对是 startDrag() 行。我想也许正在创建的阴影视图正在以某种方式捕获运动事件,但我无法阻止这种情况的发生。
-
@TheAnonymous010 这是在真实设备上。最新版 Marshmellow 上的 Nexus 5。
-
@Nate 你能解决这个问题吗?