Я создаю приложение карты, в том числе стрелку местоположения, которая показывает вам, с каким способом вы сталкиваетесь, например:
Я получаю ориентацию непосредственно из SensorManager.getOrientation()
, используя первое возвращаемое значение: азимут. Когда телефон удерживается так, чтобы экран указывал над горизонтом, а на портрете стрелка отлично работала. Однако:
- Когда телефон удерживается так, что экран указывает ниже горизонта, стрелка указывает на 180 градусов от направления, в котором находится пользователь.
- Когда телефон удерживается так, чтобы экран выглядел ровно с горизонтом, стрелка не имеет понятия, как он указывает. Азимут не возвращает значимых результатов вообще.
- Когда телефон наклонен влево или вправо (или удерживается в ландшафтном режиме), стрелка наклоняется влево или вправо.
Тщательно сконструированное и научное изображение ниже показывает, что я имею в виду (где синий - пользователь, красный - направление стрелки, экран примерно обращен к лицу пользователя, а Google Maps делает именно то, что я хочу):
(Обратите внимание, что с помощью Google Maps он не выполняет последние два действия в списке, если автоматическое вращение выключено. Но я даже не на этом этапе. Одно за раз.)
Похоже, что он просто использует направление направления оси Y, как показано здесь: http://developer.android.com/reference/android/hardware/SensorEvent.html, когда я хочу, чтобы он использовал обратное направления направления оси Z, большую часть времени, и Y, когда телефон плоский. Однако, учитывая значения, возвращаемые getOrientation()
, мне пришлось бы писать сложные случаи, чтобы исправить некоторые из проблем, и случай использования телефона с горизонтальным горизонтом неразрешимый. Я уверен, что есть более простой способ.
Здесь мой код (где lastAcceleration и lastMagneticField оба исходили от внутреннего датчика):
float[] rotationMatrix = new float[9];
if(SensorManager.getRotationMatrix(rotationMatrix, null, lastAcceleration, lastMagneticField)){
float[] orientMatrix = new float[3];
SensorManager.getOrientation(rotationMatrix, orientMatrix);
orientation = orientMat[0]*180/(float)Math.PI;
}
Что я делаю неправильно? Есть ли более простой способ сделать это?
Изменить: просто для уточнения, я делаю предположение, что пользователь держит устройство перед собой, и экран указывает на них. Помимо этого, я, очевидно, не могу сказать, вращается ли только один из них. Кроме того, я использую движение пользователя, когда он движется, но это происходит, когда они неподвижны.