title: How to implement the GestureListener.onFling() method
body: <p>There are many questions like this, but most of them are asking on HOW to set GestureDetector to a View. I have done that already, and now I'm wondering, that android has provided nothing to let an image fling.
  The problem I have is that I don't know what to do with the velocityX/Y provided in that method. 
  My last try looks like this:    </p>
  
  <pre><code>public class TouchableImage extends SizeableImage 
      implements GestureDetector.OnGestureListener, 
      GestureDetector.OnDoubleTapListener,
      OnTouchListener{
  
      protected GestureDetector mDetector;
  
      protected Matrix mCurrentMatrix;
  
      public TouchableImage(Context context) {
          super(context);
          init();
      }
  
      public TouchableImage(Context context, AttributeSet attrs) {
          super(context, attrs);
          init();
      }
  
      protected void init() {
          mCurrentMatrix = new Matrix();
          mDetector = new GestureDetector(getContext(), this);
          mDetector.setOnDoubleTapListener(this);
          if (hasImage()){
              onNewImage();
  
          }
      }
  
      private void onNewImage() {
          setOnTouchListener(this);
          setScaleType(ScaleType.MATRIX);
          setImageMatrix(mCurrentMatrix);
      }
  
      @Override
      public void setImageDrawable(Drawable d){
          super.setImageDrawable(d);
          onNewImage();
      }
  
  
  
      @Override
      public void setImageBitmap(Bitmap bm) {
          super.setImageBitmap(bm);
          onNewImage();
      }
  
      public boolean hasImage(){
          return getDrawable() != null;
      }
  
      /*GestureDetector.OnGestureListener */
      @Override
      public boolean onDown(MotionEvent e) {
          // do nothing on one finger down
          return true;
      }
  
      @Override
      public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
              float velocityY) {
          LogCat.d("ZoomableImage_FLING", "x:" + velocityX + " y:" + velocityY);
          float distanceX = velocityX / 1000;
          float distanceY = velocityY/ 1000;
          long end = System.currentTimeMillis() + (long)(Math.abs(velocityX)&gt; Math   .abs(velocityY) ? Math.abs(velocityX) / 8: Math.abs(velocityY)/8);
              long now = System.currentTimeMillis();
  
          while (now &lt; end){
              FlingRunnable fr = new FlingRunnable(e1, e2, distanceX, distanceY);
              postDelayed(fr, 10);
              distanceX -= distanceX / 100;
              distanceY -= distanceY / 100;
              now = System.currentTimeMillis();
          }
  
          return true;
      }
  
      @Override
      public void onLongPress(MotionEvent e) {
          // do nothing onLongPress       
      }
  
      @Override
      public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
              float distanceY) {
          LogCat.d("ZoomableImage_SCROLL", "x:" + distanceX + " y:" + distanceY);
          mCurrentMatrix.postTranslate(distanceX * -1, distanceY *-1);
          setImageMatrix(mCurrentMatrix);
          return true;
      }
  
      @Override
      public void onShowPress(MotionEvent e) {
          // do nothing onShowPress
      }
  
      @Override
      public boolean onSingleTapUp(MotionEvent e) {
          // do nothing onSingleTapUp
          return true;
      }
  
  
      /*GestureDetector.OnDoubleTapListener*/
      @Override
      public boolean onDoubleTap(MotionEvent e) {
          // TODO Auto-generated method stub
          return false;
      }
  
      @Override
      public boolean onDoubleTapEvent(MotionEvent e) {
          // TODO Auto-generated method stub
          return false;
      }
  
      @Override
      public boolean onSingleTapConfirmed(MotionEvent e) {
          // TODO Auto-generated method stub
          return false;
      }
  
      /* Images onTouchListener */
      @Override
      public boolean onTouch(View v, MotionEvent event) {
          /* simply dispatch the motion Events to our GestureDetector */
          return mDetector.onTouchEvent(event);
      }
  
  
      /* sizeable Image*/
      @Override
      public Matrix getCurrentMatrix() {
          return mCurrentMatrix;
      }
  
      @Override
      public void setImageBounds(PointF point) {
  
      }
  
      public class FlingRunnable implements Runnable{
  
  
          public MotionEvent e1;
          public MotionEvent e2;
          public float distanceX;
          public float distanceY;
  
          public FlingRunnable(MotionEvent e1, MotionEvent e2, float distanceX, floa t distanceY){
                  this.e1 = e1;
              this.e2 = e2;
              this.distanceX = distanceX;
              this.distanceY = distanceY;
          }
  
          @Override
          public void run() {
              onScroll(e1, e2, distanceX, distanceY);
          }
  
      }
  
  }    
  </code></pre>
  
  <p>One problem that I have is to find reasonable values for <code>distanceX/Y</code>  and for <code>end</code>.
  Another problem that I have is that even if I have some values, the <code>fling()</code> seems to appear "at once" so like all <code>onScroll()</code> calls are added and applied at the same time.</p>
  
  <p>NOTE: My build-target is 2.1 (Eclair) so I cannot use better detectors invented in 2.2 (Froyo)</p>