【Android】ScaleGestureDetectorを使う

投稿者: | 2015年5月13日

ピンチインとピンチアウトによって画像を拡大縮小させたいときは
ScaleGestureDetectorを使うと便利である。
今回はこのクラスの使い方を紹介する。

始めに、サンプルアプリの画面を示す。

device-1
device-2

画面の中央に青い四角が表示されている。これを、ピンチインとピンチアウトで拡大縮小できるようにする。

それでは、ソースコードを示す。
以下は、今回の処理を行うために作ったカスタムビューのソースコードである。
このビューの処理概要は以下の通り。
・タッチイベントを受け、それをScaleGestureDetectorに渡す
・ピンチインとピンチインの動作に応じて倍率を決定し、画面の中央に正方形を表示する
MyView.java

public class MyView extends View {
    private static final int RECT_SIZE = 64;

    private float mScale = 1.0f; // 描画する倍率
    private ScaleGestureDetector mScaleDetector;

    private Paint mRectPaint = new Paint();
    private Paint mTextPaint = new Paint();
    {
        mRectPaint.setStyle(Paint.Style.STROKE);
        mRectPaint.setColor(Color.BLUE);
        mRectPaint.setStrokeWidth(2.0f);

        mTextPaint.setTextSize(64.0f);
    }

    public MyView(Context context) {
        super(context);

        mScaleDetector = new ScaleGestureDetector(context, 
                new ScaleGestureDetector.OnScaleGestureListener() {
            @Override
            public boolean onScale(ScaleGestureDetector detector) {
                // ピンチイン・アウト中に継続して呼び出される
                // getScaleFactor()は
                // 『今回の2点タッチの距離/前回の2点タッチの距離』を返す
                Log.d("MyView", "MyView.onScale factor:" +
                 detector.getScaleFactor());

                // 表示倍率の計算
                mScale *= detector.getScaleFactor();
                invalidate();
                return true;
            }

            @Override
            public boolean onScaleBegin(ScaleGestureDetector detector) {
                Log.d("MyView", "MyView.onScaleBegin");
                return true;
            }

            @Override
            public void onScaleEnd(ScaleGestureDetector detector) {
                Log.d("MyView", "MyView.onScaleEnd");
            }
        });
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        // 受けたMotionEventを
        // そのままScaleGestureDetector#onTouchEvent()に渡す
        return mScaleDetector.onTouchEvent(event);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        // 現在の表示倍率を表示
        canvas.drawText("Scale:" + mScale, 0, 72, mTextPaint);

        // 正方形の1辺の長さを求める
        float rectSize = RECT_SIZE * mScale;

        // 描画位置をViewの中心にする
        float left = getWidth() / 2 - rectSize / 2;
        float top = getHeight() / 2 - rectSize / 2;
        float bottom = top + rectSize;
        float right = left + rectSize;

        // 正方形の描画
        canvas.drawRect(left, top, right, bottom, mRectPaint);
    }
}

20行目 コンストラクタでScaleGestureDetectorのインスタンスを作る。
第2引数でOnScaleGestureListenerを継承したクラスを渡している。
このクラスのオーバーライドメソッドであるonScale(),onScaleBegin(),onScaleEnd()に独自の実装を書くことによって、ピンチイン・ピンチアウトが行われたときの挙動を制御することができる。

23行目 OnScaleGestureListener#onScale()はピンチイン・アウト動作が行われると、継続して呼び出される。
 getScaleFactor()は前回のonScale呼び出し時と今回のonScale呼び出し時のタッチの距離の比率である。
 scaleFactor > 1.0 ならば拡大、scaleFactor < 1.0 ならば縮小となる。
 この比率を描画倍率に掛け、画面を更新する。

57行目~ 描画処理となる。
 Viewの中心に現在の倍率で正方形を描画している。

以上でピンチイン・アウトに対応して描画の拡大縮小を行う処理ができた。
最後に、参考のため上記のカスタムビューをActivityで使うときのコード例を示す。
Activity.java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(new MyView(this));
    }

  ~ 略 ~
}

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です