Android围绕动态轴

时间:2017-09-04 13:20:56

标签: android matrix view rotation

我正在开发一个ViewGroup布局,它能够检测触摸事件并根据触摸事件缩放/旋转/平移它的子视图。我的问题是,我希望孩子围绕用户手指两个手指之间的点旋转/缩放,在其中心周围执行手势

我已经有了手势识别器,我已经能够围绕孩子的中心进行缩放/平移/旋转。我认为主要问题是将枢轴点(在我的情况下是用户的第一个和第二个指针之间的中点)转换为孩子的当前旋转。我第一次设置枢轴,它工作得很好,但是一旦我旋转视图,抬起手指,然后尝试围绕另一个枢轴旋转,视图跳转。这是它的外观(仅限旋转):

enter image description here

因此,当第一次旋转发生时,它按预期工作,并围绕两个手指之间的点旋转。但是,一旦旋转,下一个旋转将跳转到新位置。这是相关的代码:

@Override
public boolean onRotationBegin(RotationGestureDetector detector) {
    float[] coordinates = screenPointsToScaledPoints(new float[]{detector.getFocusX(), detector.getFocusY()});
    pivotX = coordinates[0];
    pivotY = coordinates[1];
    child().setPivotX(pivotX);
    child().setPivotY(pivotY);
    return true;
}

@Override
public boolean onRotate(RotationGestureDetector detector) {
    rotation += detector.getRotationDelta();
    return true;
}

private float[] screenPointsToScaledPoints(float[] a){
    mRotateMatrixInverse.mapPoints(a);
    return a;
}

private void applyScaleAndTranslation() {
    View child = child();
    child.setRotation(rotation);
    mRotateMatrix.setRotate(rotation, pivotX, pivotY);
    mRotateMatrix.invert(mRotateMatrixInverse);
}

我可能遗失的任何想法?

1 个答案:

答案 0 :(得分:0)

好的,感谢@pskink我已经设法得到了答案。关键在于 - Android ImageView Scaling and translating issue

我的主要错误是我使用单独的矩阵进行缩放,移动和旋转,而在建议的答案中,只有一个包含所有操作,这就是我最终要做的事情。这是代码中有趣的部分:

private Matrix mMatrix = new Matrix();
private Matrix mMatrixInverse = new Matrix();

@Override
protected void dispatchDraw(Canvas canvas) {
    canvas.save();
    canvas.concat(mMatrix);
    super.dispatchDraw(canvas);
    canvas.restore();
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
    doubleFingers = ev.getPointerCount() == 2;
    if (!doubleFingers) {
        // Map touch coordinates to our matrix to draw correctly in the canvas.
        float[] mapped = screenPointsToScaledPoints(new float[]{ev.getX(0), ev.getY(0)});
        ev.setLocation(mapped[0], mapped[1]);
    }
    return super.dispatchTouchEvent(ev);
}

private float[] screenPointsToScaledPoints(float[] a){
    mMatrix.invert(mMatrixInverse);
    mMatrixInverse.mapPoints(a);
    return a;
}

@Override
public boolean onScale(ScaleGestureDetector detector) {
    float scaleFactor = detector.getScaleFactor();
    if (scale >= MIN_CANVAS_ZOOM) {
        scale *= scaleFactor;
        scale = Math.max(MIN_CANVAS_ZOOM, Math.min(scale, MAX_CANVAS_ZOOM));
        mMatrix.postScale(scaleFactor, scaleFactor, detector.getFocusX(), detector.getFocusY());
    }
    return true;
}

@Override
public boolean onRotate(RotationGestureDetector detector) {
    rotation += detector.getRotationDelta();
    mMatrix.postRotate(detector.getRotationDelta(), detector.getFocusX(), detector.getFocusY());
    return true;
}

@Override
public boolean onTouchEvent(MotionEvent event) {
    scaleDetector.onTouchEvent(event);
    rotationDetector.onTouchEvent(event);
    // Lots of business logic
    dX = coordinates[0] - mLastTouchX;
    dY = coordinates[1] - mLastTouchY;
    mLastTouchX = coordinates[0];
    mLastTouchY = coordinates[1];
    mMatrix.postTranslate(dX, dY);
    invalidate();
    return false;
}

在我的情况下,我必须手动检测双指平移,因为单指事件用于在OpenGL表面上绘制,因此从真实世界到缩放矩阵坐标的转换。结果如下:

enter image description here