【发布时间】:2014-06-28 06:58:07
【问题描述】:
如何检测手机绕 Y 轴的旋转?
我是安卓新手。我想检测 180 度旋转。例如,我想检测用户是否翻盖放在桌子上的手机,或者用户是否在口袋里旋转手机。
我已经阅读了很多文章,但我真的不明白如何获取手机位置,然后计算另一个位置之间的角度。
我找到了例如这篇文章,但我不知道如何处理名为方向的数组:
Get device angle by using getOrientation() function
谢谢!
// 这是我的解决方案。不完全合乎逻辑,但效果很好:
public class FlipListener implements SensorEventListener {
SensorManager sensorMgr;
FlipEventReceiver receiver;
public FlipListener(Context context, FlipEventReceiver receiver) {
this.receiver = receiver;
sensorMgr = (SensorManager) context.getSystemService(Activity.SENSOR_SERVICE);
sensorMgr.registerListener(this, sensorMgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_UI);
}
public void onResume() {
sensorMgr.registerListener(this, sensorMgr.getDefaultSensor(Sensor.TYPE_GYROSCOPE), SensorManager.SENSOR_DELAY_UI);
}
public void onPause() {
sensorMgr.unregisterListener(this);
clearStack();
}
private static final int IGNORE_FLIPS_AFTER_FLIP = 2500;
private static final int SAMPLING_INTERVAL = 60;
private static final int MINIMAL_STACK_SIZE_TO_FLIP = 2; // Shouldn't be lower than 2
private static final float FLIP_RADIANS = (float)Math.toRadians(140);
private static final int STACK_MAX_SIZE = 38;
private List<Float> stack = new ArrayList<Float>();
private long lastAdd = 0;
private long lastFlip = 0;
@Override
public void onSensorChanged(SensorEvent event) {
if (event.sensor.getType() == Sensor.TYPE_GYROSCOPE) {
rotationRateAroundYChanged((float)event.values[1]);
}
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
private void rotationRateAroundYChanged(float rotationRateAroundY) {
long currentTime = System.currentTimeMillis();
if (lastFlip != 0 && (currentTime - lastFlip) < IGNORE_FLIPS_AFTER_FLIP) {
return;
}
if( (currentTime - lastAdd) >= SAMPLING_INTERVAL ) {
if( Math.abs(rotationRateAroundY) > 0.3 ) { // Smaller values are unimportant. They can make only mess.
addToStack(rotationRateAroundY);
checkForFlip();
}
}
}
private void checkForFlip() {
int stackSize = stack.size();
if( stackSize < MINIMAL_STACK_SIZE_TO_FLIP ) return;
float approximateAngleSummary = 0;
float val;
for(int i = 0; i < stackSize; i++) {
val = Math.abs(stack.get(i).floatValue());
// "+ Math.pow(val/4.58, 2) )" don't have a sense. Simply it works better with it.
approximateAngleSummary += ( (val + Math.pow(val/4.58, 2) ) / 1000 ) * SAMPLING_INTERVAL;
if( approximateAngleSummary >= FLIP_RADIANS ) {
triggerFlipDetected();
clearStack();
return;
}
}
}
private void clearStack() {
stack.clear();
}
private void addToStack(float val) {
lastAdd = System.currentTimeMillis();
int stackSize = stack.size();
if( stackSize > 0 && ((stack.get(stackSize-1) > 0 ? 1 : -1) != (val>0?1:-1) || stackSize > STACK_MAX_SIZE) ) {
clearStack();
}
stack.add(val);
}
private void triggerFlipDetected() {
lastFlip = System.currentTimeMillis();
receiver.onFlipDetected();
}
public interface FlipEventReceiver {
public void onFlipDetected();
}
}
用法:
public class FlipTestActivity extends Activity implements FlipEventReceiver {
FlipListener flipListener;
boolean flipListenerActive = true;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_flip_test);
flipListener = new FlipListener(this, this);
}
public void onFlipDetected() {
// What to do when flip detected
}
@Override
protected void onResume() {
super.onResume();
if( !flipListenerActive ) {
flipListener.onResume();
flipListenerActive = true;
}
}
@Override
protected void onPause() {
super.onPause();
if( flipListenerActive ) {
flipListener.onPause();
flipListenerActive = false;
}
}
}
【问题讨论】:
-
您在标题中说 Z 轴,但在描述中说 Y 轴。你要哪一个?
-
抱歉,标题已更正,我的意思是 Y 轴。谢谢。
-
首先阅读API Documentation。看看你是否明白。
-
这很难,因为我对矩阵等一无所知:)。我正在阅读很多内容,试图编写一些代码,但它仍然无法按预期工作。
-
我删除了我以前的代码并发布了很好的工作解决方案。
标签: android vector rotation angle flip