问题
I need to rotate an image on touch and drag. now i need a degree angle when user press the imageView
and moove for rotating, kindly help me for the same.
imageView.setRotation(degree);
i need value of this degree variable in MotionEvent.ACTION_MOVE block.
回答1:
u want use the RotateGestureDetector in your project class as below given..
public class RotateGestureDetector extends TwoFingerGestureDetector {
/**
* Listener which must be implemented which is used by RotateGestureDetector
* to perform callbacks to any implementing class which is registered to a
* RotateGestureDetector via the constructor.
*
* @see RotateGestureDetector.SimpleOnRotateGestureListener
*/
public interface OnRotateGestureListener {
public boolean onRotate(RotateGestureDetector detector);
public boolean onRotateBegin(RotateGestureDetector detector);
public void onRotateEnd(RotateGestureDetector detector);
}
/**
* Helper class which may be extended and where the methods may be
* implemented. This way it is not necessary to implement all methods
* of OnRotateGestureListener.
*/
public static class SimpleOnRotateGestureListener implements OnRotateGestureListener {
public boolean onRotate(RotateGestureDetector detector) {
return false;
}
public boolean onRotateBegin(RotateGestureDetector detector) {
return true;
}
public void onRotateEnd(RotateGestureDetector detector) {
// Do nothing, overridden implementation may be used
}
}
private final OnRotateGestureListener mListener;
private boolean mSloppyGesture;
public RotateGestureDetector(Context context, OnRotateGestureListener listener) {
super(context);
mListener = listener;
}
@Override
protected void handleStartProgressEvent(int actionCode, MotionEvent event){
switch (actionCode) {
case MotionEvent.ACTION_POINTER_DOWN:
// At least the second finger is on screen now
resetState(); // In case we missed an UP/CANCEL event
mPrevEvent = MotionEvent.obtain(event);
mTimeDelta = 0;
updateStateByEvent(event);
// See if we have a sloppy gesture
mSloppyGesture = isSloppyGesture(event);
if(!mSloppyGesture){
// No, start gesture now
mGestureInProgress = mListener.onRotateBegin(this);
}
break;
case MotionEvent.ACTION_MOVE:
if (!mSloppyGesture) {
break;
}
// See if we still have a sloppy gesture
mSloppyGesture = isSloppyGesture(event);
if(!mSloppyGesture){
// No, start normal gesture now
mGestureInProgress = mListener.onRotateBegin(this);
}
break;
case MotionEvent.ACTION_POINTER_UP:
if (!mSloppyGesture) {
break;
}
break;
}
}
@Override
protected void handleInProgressEvent(int actionCode, MotionEvent event){
switch (actionCode) {
case MotionEvent.ACTION_POINTER_UP:
// Gesture ended but
updateStateByEvent(event);
if (!mSloppyGesture) {
mListener.onRotateEnd(this);
}
resetState();
break;
case MotionEvent.ACTION_CANCEL:
if (!mSloppyGesture) {
mListener.onRotateEnd(this);
}
resetState();
break;
case MotionEvent.ACTION_MOVE:
updateStateByEvent(event);
// Only accept the event if our relative pressure is within
// a certain limit. This can help filter shaky data as a
// finger is lifted.
if (mCurrPressure / mPrevPressure > PRESSURE_THRESHOLD) {
final boolean updatePrevious = mListener.onRotate(this);
if (updatePrevious) {
mPrevEvent.recycle();
mPrevEvent = MotionEvent.obtain(event);
}
}
break;
}
}
@Override
protected void resetState() {
super.resetState();
mSloppyGesture = false;
}
/**
* Return the rotation difference from the previous rotate event to the current
* event.
*
* @return The current rotation //difference in degrees.
*/
public float getRotationDegreesDelta() {
double diffRadians = Math.atan2(mPrevFingerDiffY, mPrevFingerDiffX) - Math.atan2(mCurrFingerDiffY, mCurrFingerDiffX);
return (float) (diffRadians * 180 / Math.PI);
}
}
its easy to use the class and effective rotate in that.. i hope to useful....
回答2:
In order to move and zoom the image we’ll use a neat little feature on the ImageView class called matrix transformation. Using a matrix we can represent any kind of translation, rotation, or skew that we want to do to the image
// These matrices will be used to move and zoom image
Matrix matrix = new Matrix();
Matrix savedMatrix = new Matrix();
// We can be in one of these 3 states
static final int NONE = 0;
static final int DRAG = 1;
static final int ZOOM = 2;
int mode = NONE;
@Override
public boolean onTouch(View v, MotionEvent event) {
ImageView view = (ImageView) v;
// Dump touch event to log
dumpEvent(event);
// Handle touch events here...
switch (event.getAction() & MotionEvent.ACTION_MASK) {
}
// Perform the transformation
view.setImageMatrix(matrix);
return true; // indicate event was handled
}
And in the gesture
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
savedMatrix.set(matrix);
start.set(event.getX(), event.getY());
Log.d(TAG, "mode=DRAG" );
mode = DRAG;
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
mode = NONE;
Log.d(TAG, "mode=NONE" );
break;
case MotionEvent.ACTION_MOVE:
if (mode == DRAG) {
matrix.set(savedMatrix);
matrix.postTranslate(event.getX() - start.x,
event.getY() - start.y);
}
break;
}
you need to play with Matrix class. here you can get the translate and using it you can get rotation angle. here is a tutorial for it.
After performing transformations such as rotation of a bitmap about an arbitrary point, the scale is lost. Of course, this makes sense because the bitmap is rotated inside the same bounds.
To get the real scale now, along with the most reliable degree of rotation, I had to follow this method. Hope it saves the rest of you a night or two.
you can get angle as follows :-
float[] v = new float[9];
matrix.getValues(v);
// translation is simple
float tx = v[Matrix.MTRANS_X];
float ty = v[Matrix.MTRANS_Y];
// calculate real scale
float scalex = values[Matrix.MSCALE_X];
float skewy = values[Matrix.MSKEW_Y];
float rScale = (float) Math.sqrt(scalex * scalex + skewy * skewy);
// calculate the degree of rotation
float rAngle = Math.round(Math.atan2(v[Matrix.MSKEW_X], v[Matrix.MSCALE_X]) * (180 / Math.PI));
来源:https://stackoverflow.com/questions/21453387/android-code-to-rotate-an-image-view-on-touch-or-drag-event