Sunday, November 19, 2017

Dragging a rotated view by adjusting layout params

Leave a Comment

I am trying to make a view follow my finger and do some rotation and scaling in multitouch with the following code

@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); } 

Everything is working well until the view is rotated. When it is rotated above 90 degrees and we try to drag it it's jumping around the touch point. I think it has something to do with

layoutParams.leftMargin += dx; layoutParams.topMargin += dy;  setLayoutParams(layoutParams); 

I am working to make this work for last two days with no success.

NOTE: what I am trying to achieve is to make a view drag rotate and scale with 2 fingers(drag with single finger also) I followed the drag code from Google's documentation so as to make it not jump while switching fingers. I am using this to rotate view.animate().rotationBy(a).setDuration(0).setInterpolator(new LinearInterpolator()).start();

because when i use view.setRotate(),the view is vibrating.

EDIT 1: I removed

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

and replaced it with:

//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 ); 

Now even after rotating the view is not moving around. but when i switch the active finger its jumping around from the actual position.

On ACTION_POINTER_UP i am doing this to change shift the active finger

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;             } 

0 Answers

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment