【问题标题】:Set custom anchor when dragging a View拖动视图时设置自定义锚点
【发布时间】:2014-04-22 21:22:54
【问题描述】:

我正在使用 Android Drag&Drop API 并尝试将拖动阴影的锚点设置为在 View 中进行触摸的点。默认行为是将锚点放在View 的中间。

我做了一些研究,似乎这可以通过覆盖DragShadowBuilder 类中的onProvideShadowMetrics (Point shadowSize, Point shadowTouchPoint) 方法来完成。据我了解,如果我更改 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 中,我创建了两个侦听器来为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);

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

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

【问题讨论】:

    标签: android drag-and-drop


    【解决方案1】:

    好的,就像 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);    
    }
    

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

    【讨论】:

      【解决方案2】:

      我猜问题出在这行super.onProvideShadowMetrics(shadowSize, shadowTouchPoint);

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

      所以,只需删除这一行。

      【讨论】:

      • 感谢您的回答。它没有解决我的问题,但你让我走上了正确的道路。为此 +1
      • 经过一番考虑,我决定给你赏金,因为你的回答确实帮助我解决了这个问题:)
      • 谢谢。我很高兴能提供帮助!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多