2017-11-11 113 views
13

我試圖做一個視圖按照我的手指,做多點觸控一些旋轉和縮放用下面的代碼通過調整佈局拖動旋轉視圖PARAMS

@Override 
public boolean onTouch(View view, MotionEvent motionEvent) { 

    final int action = motionEvent.getActionMasked(); 
    int newPosX,newPosY; 
    switch (action) { 
     case MotionEvent.ACTION_DOWN: { 
      final int pointerIndex = motionEvent.getActionIndex(); 
      final float x = motionEvent.getX(pointerIndex); 
      final float y = motionEvent.getY(pointerIndex); 

      RelativeLayout.LayoutParams parms = (RelativeLayout.LayoutParams) view.getLayoutParams(); 

      // Remember where we started (for dragging) 
      mLastTouchX = (int) x; 
      mLastTouchY = (int) y; 
      // Save the ID of this pointer (for dragging) 
      mActivePointerId = motionEvent.getPointerId(0); 
      break; 
     } 

     case MotionEvent.ACTION_MOVE: { 
      if(motionEvent.getPointerCount()==2){ 
       float newDist = spacing(motionEvent); 
       float scale = newDist/oldDist * view.getScaleX(); 
       view.setScaleY(scale); 
       view.setScaleX(scale); 

       float newAngle = rotation(motionEvent); 
       float a = newAngle - oldAngle; 
       view.animate().rotationBy(a).setDuration(0).setInterpolator(new LinearInterpolator()).start(); 
      } 
      // Find the index of the active pointer and fetch its position 
      final int pointerIndex = 
        motionEvent.findPointerIndex(mActivePointerId); 

      final float x = motionEvent.getX(pointerIndex); 
      final float y = motionEvent.getY(pointerIndex); 

      // Calculate the distance moved 
      final float dx = x - mLastTouchX; 
      final float dy = y - mLastTouchY; 
      RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams(); 

      layoutParams.leftMargin += dx; 
      layoutParams.topMargin += dy; 

      view.setLayoutParams(layoutParams); 

      break; 
     } 
     case MotionEvent.ACTION_POINTER_DOWN:{ 
      oldDist = spacing(motionEvent); 
      oldAngle = rotation(motionEvent); 
      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 = motionEvent.getActionIndex(); 
      final int pointerId = motionEvent.getPointerId(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 = (int) motionEvent.getX(newPointerIndex); 
       mLastTouchY = (int) motionEvent.getY(newPointerIndex); 
       mActivePointerId = motionEvent.getPointerId(newPointerIndex); 
      } 
      break; 
     } 
    } 
    return true; 

} 
    private float spacing(MotionEvent event) { 
    float x = event.getX(0) - event.getX(1); 
    float y = event.getY(0) - event.getY(1); 
    return (float) Math.sqrt(x * x + y * y); 
} 

private float rotation(MotionEvent event) { 
    double delta_x = (event.getX(0) - event.getX(1)); 
    double delta_y = (event.getY(0) - event.getY(1)); 
    double radians = Math.atan2(delta_y, delta_x); 
    return (float) Math.toDegrees(radians); 
} 

一切運作良好直到視圖旋轉。當它旋轉90度以上,我們嘗試拖動它時,它會在觸摸點周圍跳躍。我認爲這與

layoutParams.leftMargin += dx; 
layoutParams.topMargin += dy; 

setLayoutParams(layoutParams); 

我正在努力使這項工作在過去兩天沒有成功。

注意:我想實現的目標是使視圖拖動旋轉並用2個手指進行縮放(用單指拖動也是如此) 我遵循Google文檔中的拖動代碼,以便在切換手指時不會跳轉。我使用它來旋轉 view.animate()。rotationBy(a).setDuration(0).setInterpolator(new LinearInterpolator())。start();

因爲當我使用view.setRotate(),視圖是振動。

EDIT 1: 我除去

layoutParams.leftMargin += dx; 
layoutParams.topMargin += dy; 

,並用它取代:即使旋轉視圖不到處移動後

//To get the moved distance of the finger(X and Y) 

float diffX = motionEvent.getX(pointerIndex) - mLastTouchX; 
        float diffY = motionEvent.getY(pointerIndex) - mLastTouchY; 

//to get the distance from touch point and the top or left of the view 
        final float dx = motionEvent.getRawX() - (motionEvent.getRawX()-motionEvent.getX()); 
        final float dy = motionEvent.getRawY() - (motionEvent.getRawY()-motionEvent.getY()); 
        RelativeLayout.LayoutParams layoutParams = (RelativeLayout.LayoutParams) view.getLayoutParams(); 

//Settings appropriate value for the margin top and margin left. 

        layoutParams.leftMargin = (int) (((motionEvent.getRawX())-dx)+ diffX); 
        layoutParams.topMargin = (int) (((motionEvent.getRawY())-dy)+ diffY); 

查閱。但是當我切換活動手指時,它會從實際位置跳躍。

在ACTION_POINTER_UP我這樣做來改變轉向主動手指

case MotionEvent.ACTION_POINTER_UP: { 

       final int pointerIndex = motionEvent.getActionIndex(); 
       final int pointerId = motionEvent.getPointerId(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; 
        Log.d(TAG,"New pointer index :"+newPointerIndex); 
        mLastTouchX = (int) motionEvent.getX(newPointerIndex); 
        mLastTouchY = (int) motionEvent.getY(newPointerIndex); 
        mActivePointerId = motionEvent.getPointerId(newPointerIndex); 
       } 
       break; 
      } 
+1

我有類似的問題。後來,我在Medium上找到了驚人的文章和樣本。請參考以下內容。 https://blog.uptech.team/how-to-create-sriest-like-stickers-for-android-50512957c351。關心Preethi –

回答

1

通常我會建議對操縱過度運行時視圖的位置和大小,它更新了佈局不必要降低性能,難以控制,很少看起來不錯。

相反,如果你不想深究OpenGL中,那麼我的建議是一個自定義視圖,創建一個類,extend View,你以後在佈局XML,<com.packagename.MyCustomView ... />補充。 此視圖將具有整個屏幕的大小。 您@OverrideonDraw(Canvas canvas)方法,它會給你視圖的畫布,你可以使用畫布在視圖中繪製圖形。

invalidate();在你onDraw()年底告訴視圖再次嘗試和調用的onDraw()時可用,您應該停止調用它一旦用戶停止觸摸您的視圖,以便添加一些布爾它。

現在觸摸,您可以註冊觸摸像您一樣的事件,但在您的自定義視圖中,並使用來自canvas.getWidth()canvas.getHeight()的視圖的x,y和大小來確定要執行的操作。

如果您在達到onDraw()覆蓋onMeasure()之前需要視圖的大小。

綜述

這可能看起來不那麼容易,但它是,它的快速和退出高效,圖形將是順利的,如果你想要最好的結果,不怕大量的代碼,然後你可以使用OpenGl來查看繪圖,但是我不會建議你想要做什麼。

希望我明白了這個問題,並幫助你 - 祝你好運!