通过调整布局参数拖动旋转的视图

时间:2017-11-11 02:28:26

标签: java android view rotation

我正在尝试按照我的手指进行视图,并使用以下代码在多点触控中进行一些旋转和缩放

@Override
public boolean onTouch(View view, MotionEvent motionEvent) {

    final int action = motionEvent.getActionMasked();
    int newPosX,newPosY;
    switch (action) {
        case MotionEvent.ACTION_DOWN: {
            final int pointerIndex = motionEvent.getActionIndex();
            final float x = motionEvent.getX( pointerIndex);
            final float y = motionEvent.getY( pointerIndex);

            RelativeLayout.LayoutParams parms = (RelativeLayout.LayoutParams) view.getLayoutParams();

            // Remember where we started (for dragging)
            mLastTouchX = (int) x;
            mLastTouchY = (int) y;
            // Save the ID of this pointer (for dragging)
            mActivePointerId = motionEvent.getPointerId( 0);
            break;
        }

        case MotionEvent.ACTION_MOVE: {
            if(motionEvent.getPointerCount()==2){
                float newDist = spacing(motionEvent);
                float scale = newDist / oldDist * view.getScaleX();
                view.setScaleY(scale);
                view.setScaleX(scale);

                float newAngle = rotation(motionEvent);
                float a = newAngle - oldAngle;
                view.animate().rotationBy(a).setDuration(0).setInterpolator(new LinearInterpolator()).start();
            }
            // Find the index of the active pointer and fetch its position
            final int pointerIndex =
                    motionEvent.findPointerIndex( mActivePointerId);

            final float x = motionEvent.getX( pointerIndex);
            final float y = motionEvent.getY( pointerIndex);

            // Calculate the distance moved
            final float dx = x - mLastTouchX;
            final float dy = y - mLastTouchY;
            RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();

            layoutParams.leftMargin += dx;
            layoutParams.topMargin += dy;

            view.setLayoutParams(layoutParams);

            break;
        }
        case MotionEvent.ACTION_POINTER_DOWN:{
            oldDist = spacing(motionEvent);
            oldAngle = rotation(motionEvent);
            break;
        }

        case MotionEvent.ACTION_UP: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_CANCEL: {
            mActivePointerId = INVALID_POINTER_ID;
            break;
        }

        case MotionEvent.ACTION_POINTER_UP: {

            final int pointerIndex = motionEvent.getActionIndex();
            final int pointerId = motionEvent.getPointerId( pointerIndex);

            if (pointerId == mActivePointerId) {
                // This was our active pointer going up. Choose a new
                // active pointer and adjust accordingly.
                final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                mLastTouchX = (int) motionEvent.getX( newPointerIndex);
                mLastTouchY = (int) motionEvent.getY( newPointerIndex);
                mActivePointerId = motionEvent.getPointerId( newPointerIndex);
            }
            break;
        }
    }
    return true;

}
    private float spacing(MotionEvent event) {
    float x = event.getX(0) - event.getX(1);
    float y = event.getY(0) - event.getY(1);
    return (float) Math.sqrt(x * x + y * y);
}

private float rotation(MotionEvent event) {
    double delta_x = (event.getX(0) - event.getX(1));
    double delta_y = (event.getY(0) - event.getY(1));
    double radians = Math.atan2(delta_y, delta_x);
    return (float) Math.toDegrees(radians);
}

一切正常直到视图旋转。当它旋转超过90度并且我们试图拖动它时它会在触摸点周围跳跃。我认为它与

有关
layoutParams.leftMargin += dx;
layoutParams.topMargin += dy;

setLayoutParams(layoutParams);

我正在努力使这项工作最近两天没有成功。

注意:我想要实现的是使视图拖动旋转并用2个手指缩放(也用单个手指拖动) 我按照Google的文档中的拖拽代码进行操作,以便在切换手指时不会跳转。 我用它来旋转     view.animate()。rotationBy(a).setDuration(0).setInterpolator(new LinearInterpolator())。start();

因为当我使用view.setRotate()时,视图正在振动。

编辑1: 我删除了

layoutParams.leftMargin += dx;
layoutParams.topMargin += dy;

并将其替换为:

//To get the moved distance of the finger(X and Y)

float diffX = motionEvent.getX(pointerIndex) - mLastTouchX;
                    float diffY = motionEvent.getY(pointerIndex) - mLastTouchY;

//to get the distance from touch point and the top or left of the view
                    final float dx = motionEvent.getRawX() - (motionEvent.getRawX()-motionEvent.getX());
                    final float dy = motionEvent.getRawY() - (motionEvent.getRawY()-motionEvent.getY());
                    RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams();

//Settings appropriate value for the margin top and margin left.

                    layoutParams.leftMargin = (int) ((( motionEvent.getRawX() )-dx )+ diffX );
                    layoutParams.topMargin = (int) ((( motionEvent.getRawY() )-dy )+ diffY );

现在即使旋转后视图也没有四处移动。但当我切换活动手指时,它会从实际位置跳跃。

在ACTION_POINTER_UP上我这样做是为了改变活动手指的移位

case MotionEvent.ACTION_POINTER_UP: {

                final int pointerIndex = motionEvent.getActionIndex();
                final int pointerId = motionEvent.getPointerId( pointerIndex);

                if (pointerId == mActivePointerId) {
                    // This was our active pointer going up. Choose a new
                    // active pointer and adjust accordingly.
                    final int newPointerIndex = pointerIndex == 0 ? 1 : 0;
                    Log.d(TAG,"New pointer index :"+newPointerIndex);
                    mLastTouchX = (int) motionEvent.getX( newPointerIndex);
                    mLastTouchY = (int) motionEvent.getY( newPointerIndex);
                    mActivePointerId = motionEvent.getPointerId( newPointerIndex);
                }
                break;
            }

1 个答案:

答案 0 :(得分:2)

通常我建议不要在运行时过度操纵视图的位置和大小,它会不必要地更新布局,降低性能,难以控制,很少看起来很好。

相反,如果您不想深入研究OpenGl,那么我的建议是自定义视图,创建一个extend View的类,稍后您将在布局XML中添加该类, <com.packagename.MyCustomView ... />。 此视图将具有整个屏幕的大小。 您@Override方法onDraw(Canvas canvas),它会为您提供视图画布,您可以使用画布在视图中绘制图形。

invalidate();的末尾写onDraw()告诉View尝试再次调用onDraw(),一旦用户停止触摸你的视图就应该停止调用它,所以添加一些布尔值到它

现在有了触摸,您可以注册触摸事件,就像在自定义视图中一样触摸事件,并使用canvas.getWidth()canvas.getHeight()中的x,y和视图大小来确定要执行的操作做。

如果您在到达onDraw()覆盖onMeasure()之前需要视图的大小。

<强>综述

这可能看起来不那么容易,但它很快且退出效率很高,图形会很流畅,如果你想要最好的结果并且不怕大量代码那么你可以使用OpenGl查看绘图但是我不会建议你做什么。

希望我理解这个问题并帮助你 - 祝你好运!