如何在 View.DragShadowBuilder.onProvideShadowMetrics 中定位 canvas

How to position canvas in View.DragShadowBuilder.onProvideShadowMetrics

我有一个要求,可拖动视图需要将阴影最初直接放置在视图顶部 - 也就是说,它覆盖整个视图而不是与触摸点相关。

我一直在尝试各种方法来使它与我的 View.DragShadowBuilder 子类一起使用,但没有成功。我希望使用 drawRect 允许我指定矩形点,以便将其绘制在与我的视图相同的矩形中,但这导致没有 canvas 被绘制。

然而,仅使用canvas.drawColor(Color.CYAN)绘制矩形,但相对于触摸点。

这是我尝试使用 drawRect:

    private class VideoDragShadowBuilder extends View.DragShadowBuilder {

    public VideoDragShadowBuilder(View v) {
        super(v);
    }

    @Override
    public void onProvideShadowMetrics (Point size, Point touch) {
        int width, height;

        width = getView().getWidth();
        height = getView().getHeight();

        size.set(width, height);
        touch.set(width / 2, height / 2);
    }

    @Override
    public void onDrawShadow(Canvas canvas) {
        //canvas.drawColor(Color.CYAN);

        Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setAlpha(45);
        paint.setStyle(Paint.Style.FILL);
        paint.setColor(Color.CYAN);

        canvas.drawRect(getView().getLeft(), getView().getTop(), getView().getRight(), getView().getBottom(), paint);
    }
}

在这里,由于我触摸的位置,蓝色矩形与下面的视图略微错位 - 我希望它完全覆盖视图,无论用户触摸哪里。

public void drawRect (float left, float top, float right, float bottom, Paint paint) Added in API level 1

Draw the specified Rect using the specified paint. The rectangle will be filled or framed based on the Style in the paint. Parameters left The left side of the rectangle to be drawn top The top side of the rectangle to be drawn right The right side of the rectangle to be drawn bottom The bottom side of the rectangle to be drawn paint The paint used to draw the rect

摘自 here.

如果你想用x1y1x2y2调用drawRect,你不应该传递x2y2 作为点坐标。但是,终点和起点之间的差异会产生所需的结果,因此您应该传递 x2 - x1 而不是 x2y2 - y1 而不是 y2.

原因:right不是坐标,是宽度,bottom不是坐标,是高度。

这是我使用@pskink 的建议最终得到的解决方案。我根本不必使用 drawRect,关键是设置我以前没有的触摸点,因为我没有使用 onTouchEvent。为可能遇到相同问题的任何人添加此内容。

private Point lastTouch;

public DraggableFrameLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    dragListener = new View.OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            View.DragShadowBuilder videoShadow = new DragShadowBuilder(v);
            v.startDrag(draggableData, videoShadow, null, 0);
            return true;
        }
    };
}

@Override
public boolean onTouchEvent (MotionEvent ev)    {
    lastTouch = new Point((int) ev.getX(), (int) ev.getY()) ;
    return super.onTouchEvent(ev);
}

private class DragShadowBuilder extends View.DragShadowBuilder {

    public VideoDragShadowBuilder(View v) {
        super(v);
    }

    @Override
    public void onProvideShadowMetrics (Point size, Point touch) {
        super.onProvideShadowMetrics(size, touch);

        // The touch point must be set in order for the canvas to properly fit the view
        if (lastTouch != null) {
            touch.set(lastTouch.x, lastTouch.y);
        }
    }

    @Override
    public void onDrawShadow(Canvas canvas) {
        super.onDrawShadow(canvas);
        canvas.drawColor(Color.CYAN);
    }
}