Android Two finger rotation
Improvements of the class:
- angle returned is total since rotation has begun
- removing unnecessary functions
- simplification
- get position of first pointer only after second pointer is down
public class RotationGestureDetector {
private static final int INVALID_POINTER_ID = -1;
private float fX, fY, sX, sY;
private int ptrID1, ptrID2;
private float mAngle;
private OnRotationGestureListener mListener;
public float getAngle() {
return mAngle;
}
public RotationGestureDetector(OnRotationGestureListener listener){
mListener = listener;
ptrID1 = INVALID_POINTER_ID;
ptrID2 = INVALID_POINTER_ID;
}
public boolean onTouchEvent(MotionEvent event){
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
ptrID1 = event.getPointerId(event.getActionIndex());
break;
case MotionEvent.ACTION_POINTER_DOWN:
ptrID2 = event.getPointerId(event.getActionIndex());
sX = event.getX(event.findPointerIndex(ptrID1));
sY = event.getY(event.findPointerIndex(ptrID1));
fX = event.getX(event.findPointerIndex(ptrID2));
fY = event.getY(event.findPointerIndex(ptrID2));
break;
case MotionEvent.ACTION_MOVE:
if(ptrID1 != INVALID_POINTER_ID && ptrID2 != INVALID_POINTER_ID){
float nfX, nfY, nsX, nsY;
nsX = event.getX(event.findPointerIndex(ptrID1));
nsY = event.getY(event.findPointerIndex(ptrID1));
nfX = event.getX(event.findPointerIndex(ptrID2));
nfY = event.getY(event.findPointerIndex(ptrID2));
mAngle = angleBetweenLines(fX, fY, sX, sY, nfX, nfY, nsX, nsY);
if (mListener != null) {
mListener.OnRotation(this);
}
}
break;
case MotionEvent.ACTION_UP:
ptrID1 = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP:
ptrID2 = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_CANCEL:
ptrID1 = INVALID_POINTER_ID;
ptrID2 = INVALID_POINTER_ID;
break;
}
return true;
}
private float angleBetweenLines (float fX, float fY, float sX, float sY, float nfX, float nfY, float nsX, float nsY)
{
float angle1 = (float) Math.atan2( (fY - sY), (fX - sX) );
float angle2 = (float) Math.atan2( (nfY - nsY), (nfX - nsX) );
float angle = ((float)Math.toDegrees(angle1 - angle2)) % 360;
if (angle < -180.f) angle += 360.0f;
if (angle > 180.f) angle -= 360.0f;
return angle;
}
public static interface OnRotationGestureListener {
public void OnRotation(RotationGestureDetector rotationDetector);
}
}
How to use it:
- Put the above class in a separate file
RotationGestureDetector.java
- create a private field
mRotationDetector
of typeRotationGestureDetector
in your activity class and create a new instance of the detector during the initialization (onCreate
method for example) and give as parameter a class implementing theonRotation
method (here theactivity = this
). - In the method
onTouchEvent
, send the touch events received to the gesture detector with 'mRotationDetector.onTouchEvent(event);
' - Implements
RotationGestureDetector.OnRotationGestureListener
in your activity and add the method 'public void OnRotation(RotationGestureDetector rotationDetector)
' in the activity. In this method, get the angle withrotationDetector.getAngle()
Example:
public class MyActivity extends Activity implements RotationGestureDetector.OnRotationGestureListener {
private RotationGestureDetector mRotationDetector;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mRotationDetector = new RotationGestureDetector(this);
}
@Override
public boolean onTouchEvent(MotionEvent event){
mRotationDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
@Override
public void OnRotation(RotationGestureDetector rotationDetector) {
float angle = rotationDetector.getAngle();
Log.d("RotationGestureDetector", "Rotation: " + Float.toString(angle));
}
}
Note:
You can also use the RotationGestureDetector
class in a View
instead of an Activity
.
Pinch Zoom and 2 finger Rotation the ImageView in Android
Here is the solution that worked good for me. https://stackoverflow.com/a/18276033 Only one line I should add here and that should be
- add
imageView.setRotation(imageView.getRotation() + (-angle));
inOnRotation(RotationGestureDetector rotationDetector)
method inside the activity to set the new rotation value to the ImageView
This is for basic help. Remaining of the implementation is just fine
2 Finger Rotation gesture listener in android
/** Determine the degree between the first two fingers */
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);
if (Constant.TRACE) Log.d("Rotation ~~~~~~~~~~~~~~~~~", delta_x+" ## "+delta_y+" ## "+radians+" ## "
+Math.toDegrees(radians));
return (float) Math.toDegrees(radians);
}
Two finger rotation for OSMdroid mapview
Have you taken a look at the OpenStreetMapViewer sample app? There is the RotationGestureOverlay overlay in there that specifically shows how to do this. It isn't as smooth as I would like it, but it will do the job.
Android Pinch/Two Finger rotation on view
Out of the box, Android does not have a Rotate Gesture Detector.
What you can do, however, is calculate rotation from a two point touch event. Just determine a fulcrum for your rotation (either the center point of your 2 touch points, or one of the touch points) and determine the angle delta between the first touch event and the nth touch event. You can then rotate the given Canvas by that amount using the rotate() method.
In fact, this may be pretty easy to write your own 'Gesture Detector' for.
How to detect single finger touch and two finger touch in android?
You can use MotionEvent.getPointerCount().
Distinguish two finger rotation and simple tap
Ok, after a week I found the answer. I needed to dispatch my MotionEvent to parent of my buttons using dispatchTouchEvent. ACTION_POINTER_DOWN is for checking if user uses two fingers.
Now rotation goes to mRotationDetector and taps goes to onClickListeners of the buttons underneath the TextView player.
JAVA:
player.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
MotionEvent me = MotionEvent.obtain(event);
mRotationDetector.onTouchEvent(me);
switch (event.getActionMasked()){
case (MotionEvent.ACTION_DOWN):
flag=true;
break;
case(MotionEvent.ACTION_POINTER_DOWN):
flag=false;
break;
}
buttons.dispatchTouchEvent(event);
return true;
}
});
Related Topics
How to Get Ndk-Gdb Working on Android
Difference Between Extending Lifecycleactivity,Activity,Actionbaractivity & Appcompactactivity
How to Encrypt/Decrypt String in Android
Change Checkbox Value Without Triggering Oncheckchanged
Android - Hide All Shown Toast Messages
How to Play Audio File in Android
Android Webview with Client Certificate
How to Change Font Size in Preferencescreen
Android Java - Joda Date Is Slow
Multiple Selection in Custom Listview with Cab
One Onclickhandler for Multiple Buttons
Android - Print Full Exception Backtrace to Log
Emulator Appearing Offline on M1 MAC After the Last Update of Arm64-V8A
Performing Action After Fragment Transaction Animation Is Finished
How to Write Jarlist Cache File While Creating Android Project