How to drag a rotated DragShadow?

一曲冷凌霜 提交于 2019-12-10 19:55:03

问题


I rotated a TextView with ObjectAnimator like this:

ObjectAnimator rotate = ObjectAnimator.ofFloat(aRotatedTextView, "rotation", 0f, someAngle);

Now, I try to drag and drop the rotated(!) TextView on long click like this:

public boolean onLongClick(View view) {
    ClipData data = ClipData.newPlainText("DragData", (String) view.getTag());
    DragShadowBuilder dragShadowBuilder = new View.DragShadowBuilder(view);
    mDragInProgress = view.startDrag(data, dragShadowBuilder, view, 0);
    view.setVisibility(View.INVISIBLE);
    return true;
}

What happens is that a DragShadow is created without rotation (angle==0). I've seen quite a few examples with bitmaps (but not with rotation) that I wasnt able to get working. Is there a way to create a rotated DragShadow?


回答1:


Needed the same thing. Implemented it like this (scaling also included)

new OnTouchListener() {
    @Override
    public boolean onTouch(final View view, MotionEvent event) {

    switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN:
    double rotationRad = Math.toRadians(view.getRotation());
    final int w = (int) (view.getWidth() * view.getScaleX());
    final int h = (int) (view.getHeight() * view.getScaleY());
    double s = Math.abs(Math.sin(rotationRad));
    double c = Math.abs(Math.cos(rotationRad));
    final int width = (int) (w * c + h * s);
    final int height = (int) (w * s + h * c);
    DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view) {
        @Override
        public void onDrawShadow(Canvas canvas) {
            canvas.scale(view.getScaleX(), view.getScaleY(), width / 2,
                    height / 2);
            canvas.rotate(view.getRotation(), width / 2, height / 2);
            canvas.translate((width - view.getWidth()) / 2,
                    (height - view.getHeight()) / 2);
            super.onDrawShadow(canvas);
        }

        @Override
        public void onProvideShadowMetrics(Point shadowSize,
                Point shadowTouchPoint) {
            shadowSize.set(width, height);
            shadowTouchPoint.set(shadowSize.x / 2, shadowSize.y / 2);
        }
    };

    view.startDrag(null, shadowBuilder, view, 0);
    ...
}



回答2:


I have been going around in circles with this myself and haven't found much help on various forums.

My observation is that even when the view is rotated, the canvas that is provided to the shadow builder is in original un-rotated state.

The closest I got to a properly rotated drag shadow was by implementing a custom shadow builder and passing it the current rotation of the view being dragged.

In onProvideShadowMetrics(Point size, Point touch), I set the shadow dimensions based on the current rotation so that for rotated views, there would be enough height for the shadow to be drawn

In onDrawShadow(Canvas canvas), I take into account the rotation again and roate the canvas by the same amount as the view. I then let the base class create the actual shadow by calling super.onDrawShadow(canvas). The point of rotation is the same as that used when rotating the actual view.

The end result is that I have a rotated drag shadow which is partially clipped. It appears that even though the canvas rotation is being used in the base class, the drawing point is so close to the edge of the canvas that part of the shadow gets clipped. I have not been able to work out how to adjust the canvas so that the drawing in the base class gets done at the right offset to prevent the clipping.

It appears that I will probably end up doing all the shadow drawing myself without relying on the base class.

good luck.

m.a

Update:

Thank you Vi rus. I've finally revisited this part of my app and tried your suggested approach which has worked quite well. I can't vote up since I don't have enough points etc.



来源:https://stackoverflow.com/questions/17049938/how-to-drag-a-rotated-dragshadow

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!