gpt4 book ai didi

Android 两指旋转

转载 作者:IT老高 更新时间:2023-10-28 22:00:30 24 4
gpt4 key购买 nike

我正在尝试在 android 中实现两个手指旋转,但是它并没有像预期的那样工作。目标是像谷歌地球一样实现旋转(两指围绕焦点旋转图像)。目前我的旋转监听器看起来像这样:

 private class RotationGestureListener {
private static final int INVALID_POINTER_ID = -1;
private float fX, fY, sX, sY, focalX, focalY;
private int ptrID1, ptrID2;

public RotationGestureListener(){
ptrID1 = INVALID_POINTER_ID;
ptrID2 = INVALID_POINTER_ID;
}

public boolean onTouchEvent(MotionEvent event){
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
sX = event.getX();
sY = event.getY();
ptrID1 = event.getPointerId(0);
break;
case MotionEvent.ACTION_POINTER_DOWN:
fX = event.getX();
fY = event.getY();
focalX = getMidpoint(fX, sX);
focalY = getMidpoint(fY, sY);
ptrID2 = event.getPointerId(event.getActionIndex());
break;
case MotionEvent.ACTION_MOVE:

if(ptrID1 != INVALID_POINTER_ID && ptrID2 != INVALID_POINTER_ID){
float nfX, nfY, nsX, nsY;
nfX = event.getX(event.findPointerIndex(ptrID1));
nfY = event.getY(event.findPointerIndex(ptrID1));
nsX = event.getX(event.findPointerIndex(ptrID2));
nsY = event.getY(event.findPointerIndex(ptrID2));
float angle = angleBtwLines(fX, fY, nfX, nfY, sX, sY, nsX, nsY);
rotateImage(angle, focalX, focalY);
fX = nfX;
fY = nfY;
sX = nfX;
sY = nfY;
}
break;
case MotionEvent.ACTION_UP:
ptrID1 = INVALID_POINTER_ID;
break;
case MotionEvent.ACTION_POINTER_UP:
ptrID2 = INVALID_POINTER_ID;
break;
}
return false;
}

private float getMidpoint(float a, float b){
return (a + b) / 2;
}
private float angleBtwLines (float fx1, float fy1, float fx2, float fy2, float sx1, float sy1, float sx2, float sy2){
float angle1 = (float) Math.atan2(fy1 - fy2, fx1 - fx2);
float angle2 = (float) Math.atan2(sy1 - sy2, sx1 - sx2);
return (float) Math.toDegrees((angle1-angle2));
}
}

但是,每当我旋转时,旋转角度会大得多,有时它会旋转到错误的一侧。有关如何解决此问题的任何想法?

顺便说一句,我在摩托罗拉 Atrix 上测试它,所以它没有触摸屏错误。

谢谢

最佳答案

类的改进:

  • 自旋转开始后返回的总角度
  • 删除不必要的功能
  • 简化
  • 仅在第二个指针向下后获取第一个指针的位置
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);
}
}

使用方法:

  1. 把上面的类放在一个单独的文件中RotationGestureDetector.java
  2. 在您的 Activity 类中创建一个 RotationGestureDetector 类型的私有(private)字段 mRotationDetector,并在初始化期间创建检测器的新实例(onCreate 方法例如)并给出一个实现onRotation方法的类作为参数(这里是activity = this)。
  3. 在方法onTouchEvent中,将接收到的触摸事件通过'mRotationDetector.onTouchEvent(event);'发送到手势检测器
  4. 在您的 Activity 中实现 RotationGestureDetector.OnRotationGestureListener 并在 Activity 中添加方法“public void OnRotation(RotationGestureDetector rotationDetector)”。在此方法中,通过 rotationDetector.getAngle()
  5. 获取角度

示例:

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

}

注意:

您还可以在 View 中使用 RotationGestureDetector 类来代替 Activity

关于Android 两指旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10682019/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com