私はこの問題に 8 時間も悩まされていたので、助けを求める時が来たと考えました。
問題を説明する前に、このサイトと Google を調べた結果、どれも役に立たなかったことをお伝えしておきます。(これは 1 つ、もう1 つ、もう1 つです。)
これが取り引きです:私は拡張するクラスを持っていますSurfaceView
(それを と呼びましょうMySurface
)そしてその中の多くのメソッドをオーバーライドします。通常、いくつかの四角形とテキスト ボックスを描画しますが、これで問題ありません。ユーザーがタッチを開始するとすぐに に変換されBitmap
、ユーザーが離すまで各フレームを描画します。
ここにこすりがあります: ユーザーが画面に 2 本の指を置き、ピンチしてズームし、パンすることができるような機能を実装したいと考えています (ただし、2 本の指でのみ)。
ピンチツーズームの実装をいくつか見つけ、次の方法でそれらをCanvas
オブジェクトに適合させました。MySurface
public void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.save();
canvas.scale(mScaleVector.z, mScaleVector.z); // This is the scale factor as seen below
canvas.translate(mScaleVector.x, mScaleVector.y); // These are offset values from 0,0, both working fine
// Start draw code
// ...
// End draw code
canvas.restore();
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
float factor = detector.getScaleFactor();
if (Math.abs(factor - 1.0f) >= 0.0075f) {
mScaleVector.z *= factor;
mScaleVector.z = Math.max(MIN_ZOOM, Math.min(mScaleVector.z, MAX_ZOOM));
}
// ...
invalidate();
return true;
}
}
public boolean onTouchEvent(MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
if (event.getPointerCount() == 2) {
if (action == MotionEvent.ACTION_POINTER_DOWN && pointerIndex == 1) {
// The various pivot coordinate codes would belong here
}
}
detector.onTouchEvent(event); // Calls the Scale Gesture Detector
return true;
}
両方の要素 (前後のスクロールとピンチによるズーム) は正常に機能しますが、大きな問題が 1 つあります。ピンチ ツー ズームを使用すると0,0
、指のポイントではなくポイントにズームインします。
これを修正するために多くの方法を試しました:
- を使用して
canvas.scale(mScaleVector.z, mScaleVector.z, mScaleVector.x, mScaleVector.y);
; 明らかに、mScaleVector
x と y の値が 0 オフセットであるため、これは望ましくない結果をもたらします。 translate()
メソッドと同じオフセットを使用する「ピボット」座標を管理しますが、これにより同じ0,0
問題が発生するか、ビューに触れたときにジャンプします。- 他の多くのこと...前述のピボット座標を使用して多くのことを行い、その位置をユーザーの最初のタッチに基づいて、連続する各ジェスチャでそのタッチに相対的に移動しようとしました。
さらに、このキャンバスは制限されている必要があるため、ユーザーは永遠にスクロールできません。ただし、.scale(sx, sy, px, py)
メソッドを使用すると、 で設定した境界を超えて物事がプッシュされ.translate()
ます。
私は... この時点で、ほとんど何に対してもオープンです。Android 4.0 ギャラリー (単一の画像を表示する場合) に見られるように、この機能を追加できることはわかっています。これを処理するソース コードを追跡しようとしましたが、役に立ちませんでした。