【问题标题】:Dragging a rotated view by adjusting layout params通过调整布局参数拖动旋转视图
【发布时间】:2018-04-24 07:55:12
【问题描述】:

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

@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 个手指使视图拖动旋转和缩放(也可以用单指拖动) 我遵循了谷歌文档中的拖动代码,以使其在切换手指时不会跳跃。 我正在使用它来旋转 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;
            }

【问题讨论】:

  • 我遇到了类似的问题。后来我在 Medium 上发现了惊人的文章和示例。请参考以下内容。 blog.uptech.team/… 。问候 Preethi

标签: java android view rotation


【解决方案1】:

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

相反,如果您不想深入研究 OpenGl,那么我的建议是自定义视图,创建一个 extend View 的类,稍后将其添加到布局 XML 中,@987654322 @。 此视图将具有整个屏幕的大小。 你@OverrideonDraw(Canvas canvas)方法,它会给你view的canvas,你可以使用Canvas在View中绘制图形。

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

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

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

夏天

这可能看起来不那么容易,但确实如此,而且它快速且高效,图形会很流畅,如果你想要最好的结果并且不怕大量代码,那么你可以使用 OpenGL 进行绘图,但是我不会建议您这样做。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-10
    • 2021-02-17
    • 2021-03-11
    相关资源
    最近更新 更多