簡體   English   中英

Android圍繞動態樞軸旋轉視圖

[英]Android rotate view around dynamic pivot

我正在開發一個ViewGroup布局,該布局能夠檢測觸摸事件並根據觸摸事件縮放/旋轉/平移其子視圖。 我的問題是我希望孩子圍繞用戶手指兩根手指之間的點旋轉/縮放, 而不是圍繞其中心進行手勢。

我已經安裝了手勢識別器,並且已經能夠圍繞孩子的中心進行縮放/平移/旋轉。 我認為主要問題是將樞軸點(在我的情況下是用戶的第一和第二指針之間的中點)轉換為孩子當前的旋轉角度。 第一次設置樞軸時,效果很好,但是一旦旋轉視圖,抬起手指,然后嘗試繞另一個樞軸旋轉,視圖就會跳轉。 這是它的外觀(僅旋轉):

在此處輸入圖片說明

因此,當第一次旋轉發生時,它會按預期工作,並繞着兩個手指之間的點旋轉。 但是,一旦旋轉,下一個旋轉將跳到新位置。 以下是相關代碼:

@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);
}

有什么想法我可能會錯過嗎?

好的,感謝@pskink,我設法找到了答案。 關鍵在這里-Android ImageView縮放和翻譯問題

我的主要錯誤是我在使用單獨的矩陣進行縮放,移動和旋轉,而在建議的答案中只有一個包含所有運算的矩陣,這就是我最終要做的。 這是代碼中有趣的部分:

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表面上繪制,因此需要從真實世界轉換為縮放的矩陣坐標。 結果如下:

在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM