我正在尝试为 android 制作一个指南针应用程序,就像我之前的许多其他人一样。
但是,我在理解整个旋转矩阵的工作方式时遇到了问题。我已经尝试了前进的道路,并提出了以下代码:
public class MainActivity extends ActionBarActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if (savedInstanceState == null) {
getSupportFragmentManager().beginTransaction()
.add(R.id.container, new PlaceholderFragment())
.commit();
}
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
/*switch (item.getItemId()) {
case R.id.action_settings:
return true;
}*/
return super.onOptionsItemSelected(item);
}
public static class PlaceholderFragment extends Fragment {
TextView degreesText;
ImageView needleView;
private SensorManager sMan;
private float[] mAcc = new float[3];
private float[] mMag = new float[3];
private float[] mRotationMatrix = new float[9];
private float[] mOrientation = new float[3];
private float fAzimuth;
private boolean firstRun;
public PlaceholderFragment() {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_main, container, false);
//Test if application has been started for the first time
firstRun = getActivity().getSharedPreferences("PREFERENCE", MODE_PRIVATE).getBoolean("firstRun", true);
if (firstRun) {
//Build warning dialog
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
//Set message and title
builder.setMessage(R.string.dialog_message).setTitle(R.string.dialog_title);
//Add dismiss button
builder.setNeutralButton(R.string.dismiss, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
//On okay click
}
});
AlertDialog dialog = builder.create();
//Show dialog
dialog.show();
}
//Set firstRun to false, so dialog doesn't show again
getActivity().getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit().putBoolean("firstRun", false).commit();
//Get text and image views
degreesText = (TextView)rootView.findViewById(R.id.degrees_text);
needleView = (ImageView)rootView.findViewById(R.id.needle);
//Set up sensor manager
sMan = (SensorManager)getActivity().getSystemService(SENSOR_SERVICE);
//Listener for magnetic and accelerometer events
SensorEventListener eventListener = new SensorEventListener() {
@Override
public void onSensorChanged(SensorEvent event) {
switch (event.sensor.getType()) {
case Sensor.TYPE_ACCELEROMETER:
mAcc = event.values.clone();
break;
case Sensor.TYPE_MAGNETIC_FIELD:
mMag = event.values.clone();
break;
}
SensorManager.getRotationMatrix(mRotationMatrix, null, mAcc, mMag);
SensorManager.getOrientation(mRotationMatrix, mOrientation);
fAzimuth = (float)Math.round(Math.toDegrees(mOrientation[0]));
fAzimuth = (fAzimuth + 360) % 360;
degreesText.setText(String.valueOf(fAzimuth));
needleView.setRotation(-fAzimuth);
}
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
};
//Register listeners for magnetic and accelerometer sensors
sMan.registerListener(eventListener, sMan.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD), SensorManager.SENSOR_DELAY_NORMAL);
sMan.registerListener(eventListener, sMan.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
return rootView;
}
}
}
只要我的手机处于纵向模式并放在平坦的表面上,它就可以很好地工作。我的问题是了解我应该怎么做才能使相同的东西在纵向和横向模式下以及当我以其他方向握住手机时。
从我读过的内容来看,我需要使用SensorManager.remapCoordinateSystem()
,但我不明白我应该提供哪两个轴,以及它是如何工作的。
任何帮助理解所有这些将不胜感激,谢谢!