次のコードを使用して、ViewPagerにカスタムImagViewを追加し、ズームシステムを設定しています。ダブルタップするとズームインし、もう一度ダブルタップするとズームアウトします。ここで、スワイプして少しズームインすると、ダブルタップするとズームアウトする機能が必要になります。
関数minZoomed()を呼び出すと、ズームアウトしますが、現在は位置が中央に配置されていません。ただし、最初に完全にズームインしてからダブルタップしてズームアウトした場合は、画像が中央に配置されます。しかし、スワイプを使用して少しズームインしてからズームアウトしようとすると、画像がランダムな場所に移動します。ズームアウト後に画像を画面の中央に配置したい
それで
まず、トータルズームアウト(中央)>ダブルタップ>フルズームイン(中央)>ダブルタップ>フルズーム(中央)
だが
まず、完全ズームアウト(中央)> SWIPE TO ZOOM>リトルズーム(中央)>ダブルタップ>フルズームアウト(変位)この問題を解決するにはどうすればよいですか?
public class ZoomImageView extends ImageView
{
Matrix matrix = new Matrix();
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
boolean isMaxed = false;
boolean zoomOut = false;
PointF last = new PointF();
PointF start = new PointF();
float minScale = 1f;
float maxScale = 3f;
float[] m;
float redundantXSpace, redundantYSpace;
float width, height;
static final int CLICK = 3;
float saveScale = 1f;
float right, bottom, origWidth, origHeight, bmWidth, bmHeight;
ScaleGestureDetector mScaleDetector;
GestureDetector mDoubleDetector;
Context context;
private CustomViewPager pager;
public ZoomImageView(Context context)
{
super(context);
super.setClickable(true);
this.context = context;
mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
mDoubleDetector = new GestureDetector(context, new DoubleTapGestureDetector());
matrix.setTranslate(1f, 1f);
m = new float[9];
setImageMatrix(matrix);
setScaleType(ScaleType.MATRIX);
setOnTouchListener(new OnTouchListener()
{
public boolean onTouch(View v, MotionEvent event)
{
mScaleDetector.onTouchEvent(event);
mDoubleDetector.onTouchEvent(event);
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
PointF curr = new PointF(event.getX(), event.getY());
switch (event.getAction())
{
case MotionEvent.ACTION_DOWN:
last.set(event.getX(), event.getY());
start.set(last);
mode = DRAG;
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG)
{
float deltaX = curr.x - last.x;
float deltaY = curr.y - last.y;
float scaleWidth = Math.round(origWidth * saveScale);
float scaleHeight = Math.round(origHeight * saveScale);
if (scaleWidth < width)
{
deltaX = 0;
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
}
else if (scaleHeight < height)
{
deltaY = 0;
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
}
else
{
if (x + deltaX > 0)
deltaX = -x;
else if (x + deltaX < -right)
deltaX = -(x + right);
if (y + deltaY > 0)
deltaY = -y;
else if (y + deltaY < -bottom)
deltaY = -(y + bottom);
}
matrix.postTranslate(deltaX, deltaY);
last.set(curr.x, curr.y);
}
break;
case MotionEvent.ACTION_UP:
mode = NONE;
int xDiff = (int) Math.abs(curr.x - start.x);
int yDiff = (int) Math.abs(curr.y - start.y);
if (xDiff < CLICK && yDiff < CLICK)
performClick();
break;
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
break;
}
setImageMatrix(matrix);
if (saveScale == minScale)
{
pager.setPagingEnabled(true);
}
else
{
pager.setPagingEnabled(false);
}
return true;
}
});
}
public void setPager(CustomViewPager pager)
{
this.pager = pager;
}
@Override
public void setImageBitmap(Bitmap bm)
{
super.setImageBitmap(bm);
bmWidth = bm.getWidth();
bmHeight = bm.getHeight();
}
public void minZoomed()
{
matrix.setScale(minScale,minScale);
setImageMatrix(matrix);
invalidate();
redundantYSpace = (float)height - (minScale * (float)bmHeight) ;
redundantXSpace = (float)width - (minScale * (float)bmWidth);
redundantYSpace /= (float)2;
redundantXSpace /= (float)2;
saveScale = minScale;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
setImageMatrix(matrix);
invalidate();
}
public void maxZoomed()
{
matrix.setScale(maxScale,maxScale);
setImageMatrix(matrix);
redundantYSpace = (float)height - (maxScale * (float)bmHeight) ;
redundantXSpace = (float)width - (maxScale * (float)bmWidth);
redundantYSpace /= (float)2;
redundantXSpace /= (float)2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
setImageMatrix(matrix);
invalidate();
saveScale = maxScale;
}
public void setMaxZoom(float x)
{
maxScale = x;
}
public void setMinZoom(float x)
{
minScale = x;
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener
{
@Override
public boolean onScaleBegin(ScaleGestureDetector detector)
{
mode = ZOOM;
return true;
}
@Override
public boolean onScale(ScaleGestureDetector detector)
{
float mScaleFactor = (float)Math.min(Math.max(.95f, detector.getScaleFactor()), 1.05);
float origScale = saveScale;
saveScale *= mScaleFactor;
if (saveScale > maxScale)
{
saveScale = maxScale;
mScaleFactor = maxScale / origScale;
}
else if (saveScale < minScale)
{
saveScale = minScale;
mScaleFactor = minScale / origScale;
}
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
if (origWidth * saveScale <= width || origHeight * saveScale <= height)
{
matrix.postScale(mScaleFactor, mScaleFactor, width / 2, height / 2);
if (mScaleFactor < 1)
{
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1)
{
if (Math.round(origWidth * saveScale) < width)
{
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
}
else
{
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
}
}
}
}
else
{
matrix.postScale(mScaleFactor, mScaleFactor, detector.getFocusX(), detector.getFocusY());
matrix.getValues(m);
float x = m[Matrix.MTRANS_X];
float y = m[Matrix.MTRANS_Y];
if (mScaleFactor < 1)
{
if (x < -right)
matrix.postTranslate(-(x + right), 0);
else if (x > 0)
matrix.postTranslate(-x, 0);
if (y < -bottom)
matrix.postTranslate(0, -(y + bottom));
else if (y > 0)
matrix.postTranslate(0, -y);
}
}
return true;
}
}
@Override
protected void onMeasure (int widthMeasureSpec, int heightMeasureSpec)
{
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
width = MeasureSpec.getSize(widthMeasureSpec);
height = MeasureSpec.getSize(heightMeasureSpec);
//Fit to screen.
float scale;
float scaleX = (float)width / (float)bmWidth;
float scaleY = (float)height / (float)bmHeight;
scale = Math.min(scaleX, scaleY);
matrix.setScale(scale, scale);
setImageMatrix(matrix);
saveScale = 1f;
// Center the image
redundantYSpace = (float)height - (scale * (float)bmHeight) ;
redundantXSpace = (float)width - (scale * (float)bmWidth);
redundantYSpace /= (float)2;
redundantXSpace /= (float)2;
matrix.postTranslate(redundantXSpace, redundantYSpace);
origWidth = width - 2 * redundantXSpace;
origHeight = height - 2 * redundantYSpace;
right = width * saveScale - width - (2 * redundantXSpace * saveScale);
bottom = height * saveScale - height - (2 * redundantYSpace * saveScale);
setImageMatrix(matrix);
}
private class DoubleTapGestureDetector extends GestureDetector.SimpleOnGestureListener
{
@Override
public boolean onDown(MotionEvent e)
{
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e)
{
if( isMaxed == false)
{
isMaxed = true;
maxZoomed();
pager.setPagingEnabled(false);
}
else
{
isMaxed = false;
minZoomed();
pager.setPagingEnabled(true);
}
return true;
}
}
}