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

Ban*_*eid 7 android drag-and-drop

我正在使用Android拖放API,并尝试将拖动阴影的锚点设置为触摸所在的点View.dafault行为是将锚点放在中间位置View.

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

我做的是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);
    }
}
Run Code Online (Sandbox Code Playgroud)

Fragment我使用拖放的地方,我创建了两个侦听器来启动一个拖动事件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;
    }
};
Run Code Online (Sandbox Code Playgroud)

我设置了两个听众:

itemView.setOnLongClickListener(mEventLongClickListener);
itemView.setOnTouchListener(mEventTouchListener);
Run Code Online (Sandbox Code Playgroud)

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

我不知道我做错了什么.也许我误解了API.任何帮助或暗示将非常感激.

Ban*_*eid 11

好吧,所以像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");
    }
}
Run Code Online (Sandbox Code Playgroud)

事实上,它将重置shadowTouchPoint到拖动的中间View.但它也将拖影初始化为正确的尺寸.虽然我希望正确设置拖动阴影尺寸,但我不想重置shadowTouchPoint.

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

@Override
public void onProvideShadowMetrics(Point shadowSize,
    Point shadowTouchPoint) {

    super.onProvideShadowMetrics(shadowSize, shadowTouchPoint);

    shadowTouchPoint.set(touchPointXCoord, touchPointYCoord);    
}
Run Code Online (Sandbox Code Playgroud)

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


Sco*_*oup 8

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

您已经更改了shadowTouchPoint的值,shadowTouchPoint.set(touchPointXCoord, touchPointYCoord);但是当调用super时,您传递的shadowTouchPoint被替换为"super"默认方法,默认行为是shadowTouchPoint的中心.

所以,只需删除此行.