How to place canvas in View.DragShadowBuilder.onProvideShadowMetrics

I have a requirement when the dragged view requires that the shadow is initially placed directly above the view, that is, it covers the entire view, and not the point of touch.

I tried all kinds to make this work with my subclass of View.DragShadowBuilder , but no luck. I was hoping that using drawRect would allow me to specify the points of the rectangle so that it was drawn in the same rectangle as my view, but that would not cause the canvas to not be drawn.

However, using canvas.drawColor(Color.CYAN) draws a rectangle, but relative to the point of touch.

Here is my attempt using 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); } } 

Here, the blue rectangle is slightly biased with the image below due to where I touched - I want it to completely overlap the view no matter where the user touches.

enter image description here

+5
source share
2 answers

In this solution, I ended up with @pskink suggestions. I didn’t need to use drawRect at all, the key set the touch point, which I did not have before, since I did not use onTouchEvent. Adding this to anyone who might have the same problem.

 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); } } 
+2
source

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

Draw the specified Rect with the specified paint. The rectangle will be filled or framed based on the style in the paint. Options on the left The left side of the rectangle, drawn on top. The top side is a rectangle for drawing on the right. The right side of the rectangle is the bottom side of the rectangle for drawing paint paint used to draw rect

Taken from here .

if you want to call drawRect with x1 , y1 , x2 , y2 , you should not pass x2 and y2 as the coordinates of the point. However, the difference between the endpoint and the startpoint gives the desired result, so you should pass x2 - x1 instead of x2 and y2 - y1 instead of y2 .

Reason: right not a coordinate, but latitude, bottom not a coordinate, but a height.

+1
source

Source: https://habr.com/ru/post/1211631/


All Articles