天天看點

Android Developers:拖動和縮放

這個課程描述了如何使用手勢來拖拽和縮放螢幕的對象,使用onTouchEvent()方法來擷取觸摸事件。這裡是這節課程使用的源代碼。 

拖動一個對象 

———————————————————————————————————————————————————————————————— 

如果你把Android3.0或者更高做為目标,你能使用内嵌的,拖和拽事件監聽器View.OnDragListener,在Drag and Drop中被描述。 

一個觸摸手勢的常見操作是用它來在螢幕中拖一個對象。下面的代碼片段讓使用者拖動一個螢幕中的圖檔。記錄如下: 

  • 在一個拖(或者滑動)操作,應用程式保持跟蹤這個最初的點(手指),即使額外的手指被放置的螢幕上。例如,想象當拖動圖檔轉動的時候,使用者在這個觸摸屏中放置了第二個手指,并且離開了第一個手指。如果應用程式僅僅是跟蹤個别的點,它會把第二點作為預設的和移動圖檔的位置。 
  • 為了阻止這個情況的發生,你的應用需要區分最初的點和任何後續的點。為此,它跟蹤在Handing Multi-Touch Gestures中被描述的ACTION_POINTER_DOWN和ACTION_POINTER_UP事件。ACTION_POINTER_DOWN和ACTION_POINTER_UP被傳遞給onTouchEvent()回調方法,當第二個點按下和擡起的時候。 
  • 在ACTION_POINTER_UP情況,這個例子提取了索引并確定活動的點的ID沒有引用一個不再觸摸螢幕的點。如果是這樣,應用程式選擇一個不同的點活動,并儲存它目前的X和Y位置。以為這杯儲存的位置被用在ACTION_MOVE情況,來計算在螢幕中的對象移動的距離,應用将總是使用從正确的點的資料來計算移動的距離。 

下面的代碼塊是一個使用者在螢幕周圍拖拽一個對象。它記錄了這個活動點的初始位置,計算這個點移動的距離,并移動這個對象到新的位置。它正确的管理了額外可能的點,如上面所描述。 

注意這個代碼塊使用getActionMasked()方法。你應該總是使用這個方法(或者更好,相容性版MotionEventCompat.getActionMasked()方法)來擷取一個活動的MotionEvent。不像老的getAction()方法,getActionMasked()方法被設計為和多點工作。它傳回被執行的動作,不包含點的索引位。 

// The ‘active pointer’ is the one currently moving our object. 
private int mActivePointerId = INVALID_POINTER_ID; 
 
@Override 
public boolean onTouchEvent(MotionEvent ev) { 
   // Let the ScaleGestureDetector inspect all events. 
   mScaleDetector.onTouchEvent(ev); 
             
   final int action = MotionEventCompat.getActionMasked(ev);  
        
   switch (action) {  
   case MotionEvent.ACTION_DOWN: { 
       final int pointerIndex = MotionEventCompat.getActionIndex(ev);  
       final float x = MotionEventCompat.getX(ev, pointerIndex);  
       final float y = MotionEventCompat.getY(ev, pointerIndex);  
            
       // Remember where we started (for dragging) 
       mLastTouchX = x; 
       mLastTouchY = y; 
       // Save the ID of this pointer (for dragging) 
       mActivePointerId = MotionEventCompat.getPointerId(ev, 0); 
       break; 
   } 
            
   case MotionEvent.ACTION_MOVE: { 
       // Find the index of the active pointer and fetch its position 
       final int pointerIndex =  
               MotionEventCompat.findPointerIndex(ev, mActivePointerId);   
            
       final float x = MotionEventCompat.getX(ev, pointerIndex); 
       final float y = MotionEventCompat.getY(ev, pointerIndex); 
            
       // Only move if the ScaleGestureDetector isn't processing a gesture. 
       if (!mScaleDetector.isInProgress()) { 
           // Calculate the distance moved 
           final float dx = x - mLastTouchX; 
           final float dy = y - mLastTouchY; 
 
           mPosX += dx; 
           mPosY += dy; 
 
           invalidate(); 
       } 
       // Remember this touch position for the next move event 
       mLastTouchX = x; 
       mLastTouchY = y; 
 
       break; 
   } 
            
   case MotionEvent.ACTION_UP: { 
       mActivePointerId = INVALID_POINTER_ID; 
       break; 
   } 
            
   case MotionEvent.ACTION_CANCEL: { 
       mActivePointerId = INVALID_POINTER_ID; 
       break; 
   } 
        
   case MotionEvent.ACTION_POINTER_UP: { 
            
       final int pointerIndex = MotionEventCompat.getActionIndex(ev);  
       final int pointerId = MotionEventCompat.getPointerId(ev, pointerIndex);  
 
       if (pointerId == mActivePointerId) { 
           // This was our active pointer going up. Choose a new 
           // active pointer and adjust accordingly. 
           final int newPointerIndex = pointerIndex == 0 ? 1 : 0; 
           mLastTouchX = MotionEventCompat.getX(ev, newPointerIndex);  
           mLastTouchY = MotionEventCompat.getY(ev, newPointerIndex);  
           mActivePointerId = MotionEventCompat.getPointerId(ev, newPointerIndex); 
       } 
       break; 
   } 
   }        
   return true; 
} 
           

使用觸摸來執行縮放 

———————————————————————————————————————————————————————————————— 

如在Detecting Common Gestures中被讨論的,GestureDetector幫助你檢查Android常用的手勢,如滑動,finging,和長按。對于滑動,Android提供了ScaleGestureDetector。GestureDetector和ScaleGestureDetector能一起使用,當你想一個View認識一個額外的手勢的時候。 

為了報告檢測到的手勢事件,手勢檢測器使用監聽對象被傳遞給它們的構造方法。ScaleGestureDetector使用ScaleGestureDetector.OnScaletureListener。Android提供ScaleGestureDetector.SimpleOnScaleGestureListener作為一個幫助類,如果你不關心所有的被報告的時間,你能繼承。 

這裡是一個代碼片段,它給了你如何執行縮放的基本想法。這裡的源代碼: 

private ScaleGestureDetector mScaleDetector; 
private float mScaleFactor = 1.f; 
 
public MyCustomView(Context mContext){ 
   ... 
   // View code goes here 
   ... 
   mScaleDetector = new ScaleGestureDetector(context, new ScaleListener()); 
} 
 
@Override 
public boolean onTouchEvent(MotionEvent ev) { 
   // Let the ScaleGestureDetector inspect all events. 
   mScaleDetector.onTouchEvent(ev); 
   return true; 
} 
 
@Override 
public void onDraw(Canvas canvas) { 
   super.onDraw(canvas); 
 
   canvas.save(); 
   canvas.scale(mScaleFactor, mScaleFactor); 
   ... 
   // onDraw() code goes here 
   ... 
   canvas.restore(); 
} 
 
private class ScaleListener  
       extends ScaleGestureDetector.SimpleOnScaleGestureListener { 
   @Override 
   public boolean onScale(ScaleGestureDetector detector) { 
       mScaleFactor *= detector.getScaleFactor(); 
 
       // Don't let the object get too small or too large. 
       mScaleFactor = Math.max(0.1f, Math.min(mScaleFactor, 5.0f)); 
 
       invalidate(); 
       return true; 
   } 
} 
           

新技術,新未來!歡迎大家關注 “1024工場”微信服務号 ,時刻關注我們的最新的技術訊息! (甭客氣!盡情的掃描或者長按!)

Android Developers:拖動和縮放