2013-05-13 3 views
3

У меня есть SVG, который я хочу масштабировать и панорамировать с помощью жестов в Android. Это работает, но не достаточно гладко для моих вкусов. Итак, как я могу улучшить этот класс, чтобы иметь плавное панорамирование, которое работает на всех уровнях масштабирования и остается под вашим пальцем, масштабируется с помощью увеличения масштаба зуба из области жестов (фокус AKA), и в качестве бонуса двойное нажатие должно привести к привязке изображение назад к 1.0? Я использую этот SVG library. Приемлемый ответ должен соответствовать этим функциональным требованиям, а не неожиданно прыгать и придерживаться GestureDetectors, если не будет случая, чтобы они просто не работали.Android Canvas - Scale and Translate

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; 
     } 
    } 
} 

ответ

1

Если (вос) рисунок Изображение не достаточно быстро, вы, возможно, придется сделать это в растровое изображение, а и прокручивать, что о.