2012-06-13 24 views
1

放大和滾動後getHitRect的偏移量是多少?縮放後的命中區域的偏移量可以計算 - (event.getX()/ ZoomLayout.mScaleFactor + ZoomLayout.mClipBound.left)但是我還沒有弄清楚縮放和滾動後命中區域的偏移量。放大和滾動後HitArea的偏移量

public class ZoomLayout extends RelativeLayout implements OnDoubleTapListener, OnGestureListener{ 


//ScalingFactor i.e. Amount of Zoom 
static float mScaleFactor = 1.0f; 

// Maximum and Minimum Zoom 
private static float MIN_ZOOM = 1.0f; 
private static float MAX_ZOOM = 2.0f; 

//Different Operation to be used 
    private final int NONE_OPERATION=0; 
    private final int DRAG_OPERATION=1; 
    private final int ZOOM_OPERATION=2; 
    private float mWidth= 1280; 
    private float mHeight=800; 

// Mode to select the operation 
    private int mode; 

//Track X and Y coordinate of the finger when it first touches the screen 
    private float mInitialX = 0f; 
    private float mInitialY = 0f; 

// Track the Bound of the Image after zoom to calculate the offset 
static Rect mClipBound; 

// mDetector to detect the scaleGesture for the pinch Zoom 
private ScaleGestureDetector mDetector; 

// mDoubleTapDetector to detect the double tap 
private GestureDetector mDoubleTapDetector; 

//Pivot point for Scaling 
static float gx=0,gy=0; 

boolean mdrag=false,mZoom=false; 

public ZoomLayout(Context context, AttributeSet attrs) { 
     super(context, attrs); 
     setWillNotDraw(false); 
     mClipBound = new Rect(); 
     // Intialize ScaleGestureDetector 
     mDetector = new ScaleGestureDetector(getContext(), new ZoomListener()); 
     mDoubleTapDetector = new GestureDetector(context,this); 
     mDoubleTapDetector.setOnDoubleTapListener(this); 
    } 


    public ZoomLayout(Context context) { 
     super(context); 
     setWillNotDraw(false); 
     mClipBound = new Rect(); 
     // Intialize ScaleGestureDetector 
     mDetector = new ScaleGestureDetector(getContext(), new ZoomListener()); 
     mDoubleTapDetector = new GestureDetector(context,this); 
     mDoubleTapDetector.setOnDoubleTapListener(this); 
    } 

    @Override 
    public boolean onTouchEvent(MotionEvent event) { 

     // Handles all type of motion-events possible 
     switch(event.getAction()) { 

     case MotionEvent.ACTION_DOWN: 
      // Event occurs when the first finger is pressed on the Screen 

      Log.d("ZoomPrint", "Event: Action_Down "); 
      mInitialX = event.getX(); 
      mInitialY = event.getY(); 

     break; 
     case MotionEvent.ACTION_POINTER_DOWN: 
      //Event occurs when the second finger is pressed down 

      Log.d("ZoomPrint", "Event: Action_Pointer_Down "); 
      // If second finger is pressed on the screen with the first set the Mode to Zoom operation 
      mode=ZOOM_OPERATION; 

      break; 
     case MotionEvent.ACTION_POINTER_UP: 
      Log.d("ZoomPrint", "Event: Action_Pointer_UP "); 
      mdrag=true; 

     case MotionEvent.ACTION_UP: 
      //Event occurs when all the finger are taken of the screen 
      Log.d("ZoomPrint", "Event: Action_UP "); 
      //If all the fingers are taken up there will be no operation 
      mode = NONE_OPERATION; 
      mdrag=false; 

      break; 


     } 
     // give the event to the mDetector to get the scaling Factor 
      mDetector.onTouchEvent(event); 


     // give the event to the mDoubleTapDetector for the doubleTap 
      mDoubleTapDetector.onTouchEvent(event); 

     if(!mdrag) 
      invalidate(); 

    return true; 
    } 


    @Override 
    public boolean onInterceptTouchEvent(MotionEvent ev) { 
     onTouchEvent(ev); 
     return super.onInterceptTouchEvent(ev); 
    // return true; 
    } 







    @Override 
    public ViewParent invalidateChildInParent(int[] location, Rect dirty) { 
     return super.invalidateChildInParent(location, dirty); 
    } 




    @Override 
    protected void onLayout(boolean changed, int l, int t, int r, int b) 
    { 
     int count = getChildCount(); 
     for(int i=0;i<count;i++){ 
      View child = getChildAt(i); 
      if(child.getVisibility()!=GONE){ 
       RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams)child.getLayoutParams(); 
       child.layout(
        (int)(params.leftMargin), 
        (int)(params.topMargin), 
        (int)((params.leftMargin + child.getMeasuredWidth())), 
        (int)((params.topMargin + child.getMeasuredHeight())) 
        ); 
      } 
     } 
    } 



    @Override 
    protected void dispatchDraw(Canvas canvas) { 

     //Save the canvas to set the scaling factor returned from detector 
     canvas.save(Canvas.MATRIX_SAVE_FLAG); 

     canvas.scale(mScaleFactor, mScaleFactor,gx,gy);  

     super.dispatchDraw(canvas); 

     mClipBound = canvas.getClipBounds(); 

      canvas.restore(); 
    } 



    private class ZoomListener extends ScaleGestureDetector.SimpleOnScaleGestureListener { 


      @Override 
      public boolean onScale(ScaleGestureDetector detector) { 
       // getting the scaleFactor from the detector 
       mScaleFactor *= detector.getScaleFactor();    // gives the scaling factor from the previous scaling to the current 
      // Log.d("ZoomPrint", "detector scaling Factor" + mScaleFactor); 

       gx = detector.getFocusX(); 
       gy = detector.getFocusY(); 
       // Limit the scale factor in the MIN and MAX bound 
       mScaleFactor= Math.max(Math.min(mScaleFactor, MAX_ZOOM),MIN_ZOOM); 
      // Log.d("ZoomPrint", "Bounded scaling Factor" + mScaleFactor); 

       /*//Force canvas to redraw itself only if the one event is to happen (say Zooming only) else do not invalidate here for multi operations 
        As what we de for scrolling or panning will not reflect here. So we will add this in onDraw method 
       invalidate();*/ 
       // Here we are only zooming so invalidate has to be done 
      // invalidate(); 
      // requestLayout(); 

       // we have handle the onScale 
       return true; 
      } 



     } 


     @Override 
     public boolean onDoubleTap(MotionEvent e) { 

     // Make the mScaleFactor to its normal value 
      if(mScaleFactor>1.0f) 
      { 
        mScaleFactor=1.0f; 
      } 
     // Force the canvas to redraw itself again as the changes has been occured. 
     invalidate(); 
     requestLayout(); 
      return false; 
     } 


     @Override 
     public boolean onDoubleTapEvent(MotionEvent e) { 
     // Log.d("ZoomPrint", "OnDoubleTapEvent"); 
      return false; 
     } 


     @Override 
     public boolean onSingleTapConfirmed(MotionEvent e) { 
     // Log.d("ZoomPrint", "OnSingleTap"); 
      return false; 
     } 


     @Override 
     public boolean onDown(MotionEvent e) { 
      // TODO Auto-generated method stub 
      return false; 
     } 


     @Override 
     public boolean onFling(MotionEvent e1, MotionEvent e2, 
       float velocityX, float velocityY) { 
      return false; 
     } 


     @Override 
     public void onLongPress(MotionEvent e) { 

     } 


    @Override 
      public boolean onScroll(MotionEvent e1, MotionEvent e2, 
        float distanceX, float distanceY) { 

        int distX= (int) distanceX, distY =(int) distanceY; 

     //Log.d("Print"," X " + this.mClipBound.left +" Y " + this.mClipBound.right + " b "+ this.mClipBound.bottom + " g" + this.mClipBound.top) ; 

     Log.d("Print", "Scroll X " + distanceX + " Y " + distanceY);  

       if(this.mClipBound.left<=0) 
        this.scrollTo(-280, 0); 
       else if(this.mClipBound.top<=0) 
        this.scrollTo(0, -250); 
        else if (this.mClipBound.right>=1047) 
         this.scrollTo(280, 0); 
        else if (this.mClipBound.bottom>=800) 
         this.scrollTo(0, 250); 
        else 
        this.scrollBy((int)distanceX,(int)distanceY); 


        return true; 

      } 


     @Override 
     public void onShowPress(MotionEvent e) { 

     } 


     @Override 
     public boolean onSingleTapUp(MotionEvent e) { 
      return false; 
     } 

回答

1

您需要在滾動功能期間翻譯畫布。我已經以這種方式在我的代碼做了它:

canvas.translate(getScrollX(), getScrollY()); 

getScrollX和Y是滾動的量。

+0

它不會滾動當我在canvas.scale之前添加canvas.translate(getScrollX(),getScrollY())在上面的dispatchdraw?我錯過了什麼? – user1169079

+0

我getScrolLX()值爲零,即使我滾動? ? – user1169079

+0

是的,你錯過了一些男人。我擴展了WebView,它有它自己的滾動方法,它給你該死的完美價值。在你的情況下,你必須手動計算滾動量。 –