MatrixのpostScaleで画像を拡大縮小させる
ImageViewなり、自分で作ったCustom Viewなりで表示させる画像を、動かしたり拡大縮小させたりするのに使えるMatrixをいじって学んだことのメモです。
特にpostScaleを使った拡大縮小がイメージ通りに動かなくてハマってしまいました。
ちなみにMatrixクラスを使ってBitmapを加工する – Techoboosterを参考に始めました。
ImageViewに設定するには、setImageMatrixメソッドでMatrixを渡してやるといいです。
Matrix matrix = new Matrix();
ImageView.setImageMatrix(Matrix);
CustomViewで使う場合は、オーバーライドしたonDraw()で描画するときにMatrixを渡せばいいです。
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
canvas.drawBitmap(mImage, mMatrix, mPaint);
}
こんな感じ。mImageはBitmapオブジェクトで、mMatrixとmPaintはそれぞれnew Matrix(),new Paint()したものを渡してます。
今回は下のCustom ViewでMatrixを操作していて分かったことを書きます。
画面上を指でなぞると、その動きに応じて画像も移動するようにする場合はこうすればOK。
mMatrix.postTranslate(float X移動量,float Y移動量);
移動量を取得するにはTouchEventを自分で判定するなり、GestureDetectorを使うなりして取得します。
GestureDetectorの使い方はDetecting Common Gestures – Android Developers参照。また別途記事書こうと思います。
移動に関しては特に難しくはありませんでした。ただし、移動制限を設けようとするとこれはこれでまた大変そうです。
こちらの記事が移動制限を実装するのに非常に役立ちそうな予感です。実装できたらまた記事書きたいと思います(そればっか)。
ピンチイン・アウトで画像を拡大縮小させる場合がクセモノでした。
mMatrix.postScale(float X拡大率, float Y拡大率, float 拡大の起点X, float 拡大の起点Y);
ハマったポイントはここで渡す拡大率の扱いです。
postScaleに渡す拡大率は、Matrixを指定した拡大率に変形させるのではありません。現在のMatrixを渡した拡大率で拡大縮小させます。Matrixの拡大率が0.1のときにpostScale(0.1f,0.1f)するとMatrixの拡大率は0.01になります。
画像が過剰に縮小・拡大されないように渡す拡大率の値を制限したとしても、制限した値をそのまま渡してしまったら制限が効きません。
指定した拡大率に画像を変形させたい場合は変化量を計算して渡すようにします。
ScaleGestureDetectorを使って拡大縮小させていて、頭の中がこんがらがっていました(現在進行形ですけど)。ScaleGestureDetectorを使うと、onScaleメソッド内でdetector.getScaleFactor()を使うことでピンチイン・アウトによる拡大率を取得することができます。
この拡大率は、ピンチ操作が始まった段階では1.0から始まります。そのためこの値をそのままMatrixのpostScaleに渡すと、拡大縮小の開始時に一旦元の縮尺に戻ってしまいます。そのこととごっちゃになっていて間違ったこと書いてました。
float deltaScale = targetScale / nowScale;
mMatrix.postScale(deltaScale, deltaScale);
postScaleではなくsetScaleを使う方法もあるのかもしれませんが、動き始めに画像が元のサイズに戻ってしまうため、この方法がスマートな気がします。

















