2017-11-11 114 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来查看绘图,但是我不会建议你想要做什么。

希望我明白了这个问题,并帮助你 - 祝你好运!