Java startDrag导致操作\u立即停止,然后是操作\u取消

Java startDrag导致操作\u立即停止,然后是操作\u取消,java,android,Java,Android,我有一个几乎全屏的视图,底部有一个水平的RecyclerView(在自定义视图中)。我试图将元素从RecyclerView拖到页面上半部分的视图上。我试着听一个点击和一个拖动,但大多数时候,我不能让触控监听器返回除“ACTION\u DOWN”和“ACTION\u CANCEL”之外的任何内容 一件非常恼人的事情是,如果我设置断点并进入调试模式,它就可以正常工作。我得到ACTION\u DOWN->ACTION\u UP->ACTION\u DOWN->ACTION\u UP。有时它在第一次发布

我有一个几乎全屏的视图,底部有一个水平的RecyclerView(在自定义视图中)。我试图将元素从RecyclerView拖到页面上半部分的视图上。我试着听一个点击和一个拖动,但大多数时候,我不能让触控监听器返回除“ACTION\u DOWN”和“ACTION\u CANCEL”之外的任何内容

一件非常恼人的事情是,如果我设置断点并进入调试模式,它就可以正常工作。我得到ACTION\u DOWN->ACTION\u UP->ACTION\u DOWN->ACTION\u 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);
    }
}
如果我添加一条log语句,将motionEvent立即打印为onTouch中的第一行,那么它始终是ACTION\u DOWN,紧接着是ACTION\u 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(),到处添加RequestDisallowWinterCeptTouchEvent(true),到处覆盖onInterceptTouchEvent(),但都没有效果

我在这里发现了其他类似的问题,但都没有答案:

任何帮助都将不胜感激。谢谢


编辑


今天早上我意识到,当记录上面的触摸事件时,取消操作来自另一个位置。该触摸事件的x和y值与开始动作的x和y值截然不同。我认为它们对应于x和y,其中拖动的阴影对应于活动。不过我还是没能把它修好

我刚刚检查并添加了onTouchListeners,它对我在整个层次结构中可以访问的每个视图返回false,这种行为仍然在发生。如果我在我的活动上覆盖dispatchTouchEvent,这些事件看起来很好,所以它发生在嵌套在更下面的某个地方


我还禁用了所有动画和拉刷新,但没有骰子。

据我所知,
view.startDragAndDrop()
view.startDrag()
只能在不同容器/放置区域之间拖动时使用。我认为这就是方法名称更改的原因(因为它们之间没有区别)

如果您只是试图拖动一个
图像视图
,则无需使用
view.startdragandrop()
。为此,您可以简单地执行以下操作:

class YourActivity: AppCompatActivity() {
    private var imageWidth = 0
    private var imageHeight = 0

    override fun onCreate(savedInstanceState: Bundle?) {
        val imageToMove = findViewById<ImageView>(R.id.your_image)

        // get the size of the image, so we can adjust the touch coords later
        imageToMove.post {
            imageWidth = imageToMove.width
            imageHeight = imageToMove.height
        }

        imageToMove.setOnTouchListener { view, event ->
            when (event.action) {
                MotionEvent.ACTION_MOVE -> {
                    // adjust the event coords based on size of the image
                    // 
                    // the touch coords is the middle of the image, so need
                    // to account for that
                    view.x = event.rawX - (pinWidth / 2)
                    view.y = event.rawY - (pinHeight / 2)
                }
            }
        }
    }
}
class YourActivity:AppCompatActivity(){
私有变量imageWidth=0
私有变量imageHeight=0
重写创建时的乐趣(savedInstanceState:Bundle?){
val imageToMove=findviewbyd(R.id.your_图像)
//获取图像的大小,以便我们以后可以调整触摸坐标
图像移动邮政{
imageWidth=imageToMove.width
imageHeight=imageToMove.height
}
imageToMove.setOnTouchListener{视图,事件->
何时(事件、动作){
MotionEvent.ACTION\u MOVE->{
//根据图像大小调整事件坐标
// 
//触摸坐标位于图像的中间,因此需要
//这是为什么
view.x=event.rawX-(pinWidth/2)
view.y=event.rawY-(pinHeight/2)
}
}
}
}
}

如果您试图将视图从一个视图组拖动到另一个视图组,那么您需要使用
View.startDragAndDrop()
,然后在需要“拖动上下文感知”的视图上设置拖动侦听器。

您说过,当您注释最后一行时,问题就消失了,是吗?您是在模拟器上还是在真实设备上使用此功能?有时我在模拟器上拖动时遇到问题。@Elltz是的,这肯定是startDrag()行的问题。我想可能正在创建的阴影视图以某种方式捕获了运动事件,但我无法阻止这种情况的发生。@TheAnonymous010这是在真实的设备上。Nexus 5最新版本的Marshmellow。@Nate你能解决这个问题吗?