[英]Android Canvas - Scale and Translate
我有一個SVG,我想在Android中使用手勢進行縮放和平移。 它有效,但不夠順暢,不適合我的口味。 那么我怎樣才能改進這個類以使平滑平移在所有縮放級別下工作並保持在手指下,使用捏合手勢縮放來自手勢區域(AKA焦點)並且作為獎勵雙擊應該導致捕捉圖像回到1.0? 我正在使用這個SVG庫 。 一個可接受的答案應該滿足這些功能要求,不要意外跳轉並堅持使用GestureDetectors,除非可以說它們不起作用。
public class MapView extends ViewGroup {
private static final float MINIMUM_SCALE_FACTOR = 1.0f;
private static final float MAXIMUM_SCALE_FACTOR = 10.0f;
private Picture mPicture;
private Paint mPaint;
private ScaleGestureDetector mScaleDetector;
private GestureDetector mMoveDetector;
private float mScaleFactor;
private float mScaleFocusX;
private float mScaleFocusY;
private float mFocusX = 0.0f;
private float mFocusY = 0.0f;
private float mImageHeight;
private float mImageWidth;
private int mViewHeight;
private int mViewWidth;
private RectF mDrawingRect;
public MapView(Context context) {
super(context);
init(context);
}
public MapView(Context context, AttributeSet attrs) {
super(context, attrs);
init(context);
}
public MapView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
init(context);
}
public void init(Context context) {
Log.d(getClass().getCanonicalName(), "Initialized.");
this.setBackgroundColor(Color.WHITE);
this.mPaint = new Paint();
mPaint.setStyle(Paint.Style.STROKE);
mPaint.setColor(Color.BLUE);
mPaint.setStrokeWidth(2);
mPaint.setAntiAlias(true);
this.mScaleFactor = MINIMUM_SCALE_FACTOR;
// Setup Gesture Detectors
this.mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());
this.mMoveDetector = new GestureDetector(context, new MoveListener());
}
@Override
protected void onLayout(boolean changed, int l, int t, int r, int b) {
Log.d(getClass().getCanonicalName(), "onLayout");
this.mDrawingRect = getDrawingSquare();
}
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {
super.onSizeChanged(w, h, oldw, oldh);
this.mViewWidth = w;
this.mViewHeight = h;
}
@Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
Log.d(getClass().getCanonicalName(), "onDraw()");
canvas.save();
canvas.scale(mScaleFactor, mScaleFactor, mScaleFocusX, mScaleFocusY);
canvas.translate(mFocusX, mFocusY);
canvas.drawRect((int) mDrawingRect.left, (int) mDrawingRect.top, (int) mDrawingRect.right, (int) mDrawingRect.bottom, mPaint);
canvas.drawPicture(mPicture, mDrawingRect);
canvas.restore();
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
mScaleDetector.onTouchEvent(ev);
mMoveDetector.onTouchEvent(ev);
return true;
}
public RectF getDrawingSquare() {
float width = getWidth();
float height = getHeight();
Log.d(getClass().getCanonicalName(), "Picture width " + width + " - height " + height);
float side = Math.min(width, height);
return new RectF(0, 0, side, side);
}
public void setSVG(SVG svg) {
Log.d(getClass().getCanonicalName(), "SVG to Picture.");
this.mPicture = svg.getPicture();
this.mImageHeight = mPicture.getHeight();
this.mImageWidth = mPicture.getWidth();
invalidate();
}
private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
@Override
public boolean onScale(ScaleGestureDetector detector) {
mScaleFactor *= detector.getScaleFactor(); // scale change since previous event
mScaleFocusX = detector.getFocusX();
mScaleFocusY = detector.getFocusY();
// Don't let the object get too small or too large.
mScaleFactor = Math.max(MINIMUM_SCALE_FACTOR, Math.min(mScaleFactor, MAXIMUM_SCALE_FACTOR));
invalidate();
return true;
}
}
private class MoveListener extends GestureDetector.SimpleOnGestureListener {
// @Override
// public boolean onDown(MotionEvent e) {
// return true;
// }
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
scrollBy((int)distanceX, (int)distanceY);
// mFocusX += distanceX;
// mFocusY += distanceY;
// return true;
return true;
}
}
}
如果(重新)繪制圖片的速度不夠快,您可能不得不將其繪制到位圖而是滾動它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.