拖动视图时设置自定义锚点

我正在使用Android拖放API,并试图将拖影的锚点设置为在View中进行触摸的点。 默认行为是将锚定在View的中间。

我做了一些研究,似乎可以通过覆盖DragShadowBuilder类中的onProvideShadowMetrics (Point shadowSize, Point shadowTouchPoint)方法来DragShadowBuilder 。 从我的理解,如果我改变了shadowTouchPoint的x,y坐标,它应该修改拖动锚的坐标。

我做的是扩展DragShadowBuilder类如下所示:

 class EventDragShadowBuilder extends DragShadowBuilder { int touchPointXCoord, touchPointYCoord; public EventDragShadowBuilder() { super(); } public EventDragShadowBuilder(View view, int touchPointXCoord, int touchPointYCoord) { super(view); this.touchPointXCoord = touchPointXCoord; this.touchPointYCoord = touchPointYCoord; } @Override public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { shadowTouchPoint.set(touchPointXCoord, touchPointYCoord); super.onProvideShadowMetrics(shadowSize, shadowTouchPoint); } } 

在我使用拖放的Fragment ,我创build了两个监听器来启动一个View的拖动事件:

 mEventLongClickListener = new OnLongClickListener() { @Override public boolean onLongClick(View view) { EventDragShadowBuilder shadowBuilder = new EventDragShadowBuilder( view, mEventTouchXCoord, mEventTouchYCoord); view.startDrag(null, shadowBuilder, view, 0); return true; } }; // We need this listener in order to get the corect coordinates for the // drag shadow mEventTouchListener = new OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent event) { final int action = event.getAction(); switch (action & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: { mEventTouchXCoord = (int) event.getX(); mEventTouchYCoord = (int) event.getY(); break; } } return false; } }; 

我设置了两个听众:

 itemView.setOnLongClickListener(mEventLongClickListener); itemView.setOnTouchListener(mEventTouchListener); 

一切都OK到这里。 但是,当我testing应用程序,并开始拖动过程​​中,拖动阴影中心下的触摸点。 所以它使用默认行为。 我试着debugging,我看到mEventTouchXCoordmEventTouchYCoord设置正确。 方法shadowTouchPoint.set(touchPointXCoord, touchPointYCoord); 得到正确的坐标,但它仍然在影子的中心。

我不知道我在做什么错。 也许我误解了API。 任何帮助或提示将不胜感激。

Related of "拖动视图时设置自定义锚点"

好吧,就像Scoup说的那样,问题出在onProvideShadowMetrics()方法中。 事实是,如果我删除超级构造函数, super.onProvideShadowMetrics(shadowSize, shadowTouchPoint); ,它不会再显示拖影了。

仔细看看API方法,我发现:

 public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { final View view = mView.get(); if (view != null) { shadowSize.set(view.getWidth(), view.getHeight()); shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2); } else { Log.e(View.VIEW_LOG_TAG, "Asked for drag thumb metrics but no view"); } } 

所以确实,它会将shadowTouchPoint重置到拖动View的中间。 但是它也将拖影初始化为正确的尺寸。 虽然我想要正确设置拖影尺寸,但我不想重置shadowTouchPoint

实现这个最简单的方法是用自定义值初始化shadowTouchPoint 之前调用超级构造函数,如下所示:

 @Override public void onProvideShadowMetrics(Point shadowSize, Point shadowTouchPoint) { super.onProvideShadowMetrics(shadowSize, shadowTouchPoint); shadowTouchPoint.set(touchPointXCoord, touchPointYCoord); } 

另一个解决scheme是处理拖动阴影View自己,并完全跳过超级构造函数。 我会回来一个详细的更新。

我猜这个问题是这个行super.onProvideShadowMetrics(shadowSize, shadowTouchPoint);

您已经在shadowTouchPoint.set(touchPointXCoord, touchPointYCoord);更改了shadowTouchPoint的值shadowTouchPoint.set(touchPointXCoord, touchPointYCoord); 但是在调用super时,您传递的是被“超级”默认方法取代的shadowTouchPoint,默认行为是以shadowTouchPoint为中心。

所以,只要删除这一行。